Jump to content

Walking an NPC


Recommended Posts

Take a look at how the vast majority of navgoals are used in the game - they are hooked up via scripts which take generic parameters (common/2pointpatrol.IBI). If you're making a patrolling script that isn't too complicated, they're almost certainly already made.

 

I really don't think the range is the distance from one navgoal to another, it's the distance from its starting position to another waypoint. What I mean by this is: you want a waypoint right next to each navgoal. Your setup should then look something like this:

[N] -> [W] <--------------------> [W] <- [N]
Note that the waypoints point to the navgoal, not to each other. In one direction, this would look like:

[N] -> [W] -------------> [N]
The link going from the navgoal to the waypoint might (?) be optional, I don't remember. Basically if the white line from the navgoal extends too far in nav show all, then the discovery range is too far and you need to move the waypoint closer. The range from the waypoint shouldn't matter.

 

If you want to get a good example of waypointing, all JK2 maps do waypointing awesomely and you should definitely follow their example. JKA maps seem to be lacking hardcore in just about every important aspect. It's like they had someone play finger-painting with waypoints, it really is that bad.

therfiles and Cerez like this
Link to comment

@@Cerez i now better thas issue because was one of the first thing i fighted into my map work on SP.

welll for what i can tell you for help to you based on my esperience:

1: NPC that walk between waypoint grid should be in cinematic state. in BS_DEFAULT the AI is very stupid about following the paths.

2: the unique set of Icarus of your NPC your need are:

SET_BEHAVOUR_STATE BS_CINEMATIC.

SET_WALKING , true

SET_RUNNING, false.

and the WALKSPEED, If you want a different value by default.

you not need to use the IGNOREENEMIES and CHASEENEMIES field, if is not a fight scene, because the BS_CINEMATIC state is like the notarget consolle command and NPC will ignore other enemies entities.

 

about the grid.

there are 3 entity you need to use:

the yellow Waypoint.

the Green Waypoint_navgoal

the purple Point Combat.

how works a net grid... well

years ago i create a large swamp map with a long path into the forest. 2000 trees in the map LOL.

i placed wave of NPC mercenaries soldiers in the swamp, ambushed on the trees.

i create a very big waypoint net around the trees.

the structure was exagonal, like the cells of the lair of bees.

six waypoint connected in thay way:

   /1  ---------------2 \

 3   |      TREE      |    4

  |  5---------------- 6    |

 7  |        TREE     |   8

   \ 9  ------------- 10 /

 

 

was a VERY complex waypoint grid. i connected every waypoint to the next simply in that mode: 

1: select waypointA

2 select waypoint B

3: hit Control + K keys

however, the NPCs will fight very smarts, run, escape...  go around the trees for reach the players  and they was shooters!

Jedi -sith NPC have a certain intelligence and they can reach a target or a enemy also without the waypoint guide, if target is sufficient near.

but shooters like stormtroopers ... uff, they are so stupid. they really need a waypoint net. and net need to be complex like the path itself. in the case of a forest, the waypoint grid was very complex. i placed also many strategical point_combat around the trees and enemy ambush on that, placing back to the trees or into the bushes for shooots the player. was a wonderful battle.

 

in case of cinematic... well, you need to set into BS_cinematic state the NPC

in cinematic state you need to make this:

1: into a map add the navgoail of destination.

2: add some yellow waypoint at regular distance (512-1024 map unit each other) and connect the previous with the next with CTRL + K.

the first waypoint near to NPC is connect to second, that is connected to third, etc, the last yellow waypoint need to be connected to the green waypoint.

3: on icarus: make a "task" field for NPC. 

name task with something like "walk1"

and inside put "SET_NAVGOAL" with the targetname of the WAYPOINT_NAVGOAL green entitie.

close the task.

for the npc set istruction: DO "walk1"

if you want NPC move toward multiple destination,. instead of DO walk1 put DOWAIT walk1.

and add also the task "walk2" with the NAVGOAL waypoint 2 , a task with the navgoal waypoint 3, etc etc etc.

so NPC will make these istruction:

dowait walk1

dowait walk2

dowait walk3.

if you want NPC walk in loop:

put into a loop cycle these:

dowait walk1

dowait walk2

dowait walk3

dowait walk2

dowait walk1

 

NPC can also wait some second before begin to walk into another waypint.

dowait walk1

wait 1000

dowait walk2

wait 500

dowait walk3

wait 1500

dowait walk2

wait 3000

 

in case there is a door into the path: NPC are so stupid that if there is a door , they ignore waypoints over the doors!

for fix this you need to place two connected NAVGOAL, one to each side of the door.

                    |||||

NAVGOAL ---||--- NAVGOAL

                    |||||

 

connected with CTRL+K

 

patrol  same as BS_CINEMATIC. but you need to set an ANGERSCRIPT PAINSCRIPT or AWAKESCRIPT on NPC,

so if NPC is wounded, or angered or see the player, he turn into BS_DEFAULT state and pass to combat mode.

(npc in combat mode use the waypoint net for running and point combat as strategical point for shoot the player.

important: the point_combat entities not need to be linked to waypoint grid.

 

that's is based on my experience. with me is ever worked. :\

i have not idea why shooter NPC are so stupid to moving into maps. there is some code setting i guess.

Cerez likes this
Link to comment

Take a look at how the vast majority of navgoals are used in the game - they are hooked up via scripts which take generic parameters (common/2pointpatrol.IBI). If you're making a patrolling script that isn't too complicated, they're almost certainly already made.

 

I really don't think the range is the distance from one navgoal to another, it's the distance from its starting position to another waypoint. What I mean by this is: you want a waypoint right next to each navgoal. Your setup should then look something like this:

[N] -> [W] <--------------------> [W] <- [N]
Note that the waypoints point to the navgoal, not to each other. In one direction, this would look like:

[N] -> [W] -------------> [N]
The link going from the navgoal to the waypoint might (?) be optional, I don't remember. Basically if the white line from the navgoal extends too far in nav show all, then the discovery range is too far and you need to move the waypoint closer. The range from the waypoint shouldn't matter.

 

If you want to get a good example of waypointing, all JK2 maps do waypointing awesomely and you should definitely follow their example. JKA maps seem to be lacking hardcore in just about every important aspect. It's like they had someone play finger-painting with waypoints, it really is that bad.

 

Using this setup and BS_WANDER, I was able to get the character to do the random walk between the three navgoals, no matter how large the distance. However, my script still doesn't work with BS_DEFAULT or BS_CINEMATIC. It works in the sense that the NPC will pick a random navgoal from the three and head to it, but once the NPC has reached their first navgoal, any navgoal change given after that is ignored. This seems to be an error on the programming side of things. Could be OpenJK specific, but I have no means to test my script with the retail game to be sure.

 

This is how my script looks now, and it's set as the NPC entity's spawnscript:

rem ( "Random Walker Test Script" );

affect ( "walker", FLUSH )
{
	set ( "SET_WEAPON", "WP_NONE" );
	set ( "SET_PLAYER_TEAM", "TEAM_PLAYER" );
	set ( "SET_ENEMY_TEAM", "TEAM_ENEMY" );
	set ( "SET_BEHAVIOR_STATE", "BS_DEFAULT" );
	set ( "SET_CHASE_ENEMIES", "true" );
	set ( "SET_LOOK_FOR_ENEMIES", "true" );
	set ( "SET_IGNOREALERTS", "false" );
	set ( "SET_WALKING", "true" );
	set ( "SET_RUNNING", "false" );
	wait ( 4000.000 );
	declare ( FLOAT, "ranNum" );
	task ( "casualwalk" )
	{
		set ( "ranNum", random ( 0, 3 ) );
		if ( get ( FLOAT, "ranNum" ) > 2 )
		{
			set ( "SET_NAVGOAL", "wpoint3" );
		}
		else ()
		{
			if ( get ( FLOAT, "ranNum" ) > 1 )
			{
				set ( "SET_NAVGOAL", "wpoint2" );
			}
			else ()
			{
				if ( get ( FLOAT, "ranNum" ) > 0 )
				{
					set ( "SET_NAVGOAL", "wpoint1" );
				}
			}
		}
	}
	loop ( -1 )
	{
		do ( "casualwalk" );
		wait ( "casualwalk" );
		wait ( random ( 0, 4000 ) );
	}
}
Asgarath83 likes this
Link to comment

I worked a lot with npc moving.

 

What I know is that the eyes of the npcs must be able to watch the navgoal point placed on the ground.

If the npc cannot see it directly (without any obstacle), the npc will not move.

 

It is very difficult with stairs because the npc must be able to see the navgoal on the top of the stairs.  You must place the navgoal at the very extrem limit of the stair.

 

Here is an example :

 

 

{
"classname" "NPC_Jedi"
"NPC_type" "wookie"
"origin" "764 676 32"
"angle" "180"
"spawnflags" "32"
"health" "9999"
"spawnscript" "fja/npc_navO_ally"
}
{
"classname" "waypoint_navgoal"
"targetname" "Lave_nav1"
"origin" "764 676 32"
}
{
"classname" "waypoint_navgoal"
"targetname" "Lave_nav2"
"origin" "-780 703 32"
}
{
"classname" "waypoint_navgoal"
"targetname" "Lave_nav3"
"origin" "-795 1610 32"
}
 

and the script

 

 

(SET BS_CINEMATIC....)

 

task ( "nav1" )
    {
            set ( "SET_NAVGOAL", "Lave_nav1" );
    }

 

task ( "nav2" )
    {
            set ( "SET_NAVGOAL", "Lave_nav2" );
    }

task ( "nav3" )
    {
            set ( "SET_NAVGOAL", "Lave_nav3" );
    }

 

    loop ( -1 )
    {
        do ( "nav1" );
        wait ( "nav1" );

        do ( "nav2" );
        wait ( "nav3" );
           do ( "nav3" );
        wait ( "nav3" );

    }

 

About the random times for "wait", I know it doesnot work with OJP, so maybe it does not work with basejka or sp.

Any line with wait (Get(something)) doesnot work. I must put only numbers, like wait( 4000);

 

 

I f I was you, I would not put the random choice in the task but in the loop :

task ( "nav1" )
	{
              set ( "SET_NAVGOAL", "wpoint1" );
        }

task ( "nav2" )
	{
              set ( "SET_NAVGOAL", "wpoint2" );
        }
task ( "nav3" )
	{
              set ( "SET_NAVGOAL", "wpoint3" );
        }


loop ( -1 )
	{
          set ( "ranNum", random ( 0, 3 ) );
		if ( get ( FLOAT, "ranNum" ) > 2 )
		{
			do (nav1);
                        wait (nav1);
		}
		else ()
		{
			 if ( get ( FLOAT, "ranNum" ) > 1 )
			{
				do (nav2);
                                wait (nav2);
			}
			else ()
			{
				if ( get ( FLOAT, "ranNum" ) > 0 )
				{
					do(nav3);
                                        wait(nav3);
				}
			}
		}
		
		wait ( 4000 );
	}
Cerez and Asgarath83 like this
Link to comment

Two things you could try:

  • Setting a static wait value (it might not have enough time to idle in one spot - 1000 ms ought to be more than enough)
  • Put each SET_NAVGOAL into a task and do something like this:

 

if(random()) {
  dowait(go_to_this_spot);
} else if(random()) {
 dowait(go_to_another_spot);
}

 

But I don't understand what is wrong with BS_WANDER...? If you're trying to make an NPC wander around, that seems like the best fit.

Cerez likes this
Link to comment

But I don't understand what is wrong with BS_WANDER...? If you're trying to make an NPC wander around, that seems like the best fit.

There's nothing wrong with it in practice, but I'm trying to script an intelligent and responsive AI, and BS_WANDER only allows for a very primitive behaviour of walking moving back and forth between waypoints aimlessly.

 

I want to simulate the daily activities of a character, and for that I will need to define potential paths and behaviour, but have the character choose what to do randomly as well -- a sequence at a time.

 

What I know is that the eyes of the npcs must be able to watch the navgoal point placed on the ground.

If the npc cannot see it directly (without any obstacle), the npc will not move.

Hmm! This is an interesting tip. I was wondering about this. I think I will remove the stairs from the equation for now, and place all three test navgoals on a flat surface across the big room, so there are no obstacles in the way.

Link to comment

What I know is that the eyes of the npcs must be able to watch the navgoal point placed on the ground.

If the npc cannot see it directly (without any obstacle), the npc will not move.

 

Only if you don't have a proper waypoint network! Although the visibility rule still applies between waypoints, i.e. there must be line of sight for waypoints to connect.

Link to comment

Okay, after hours and hours and hours of testing, and scripting everything by the book, I've come to undeniable evidence that indeed a bug in the programming is responsible.

 

I've placed all three navgoals in line on a flat surface, with a corresponding waypoint next to them, and linked them all up properly (as @@eezstreet has kindly noted it in detail). The following script will half the time succeed in doing what it's supposed to, and half the time fail, sometimes in the middle of a walk from point to point, making the character walk to the next designated navgoal and stop -- despite the fact that the script is intructed to run in an infinite loop.

 

rem ( "Random Walker Test Script" );

affect ( "walker", FLUSH )
{
	set ( "SET_WEAPON", "WP_NONE" );
	set ( "SET_PLAYER_TEAM", "TEAM_PLAYER" );
	set ( "SET_ENEMY_TEAM", "TEAM_ENEMY" );
	set ( "SET_BEHAVIOR_STATE", "BS_DEFAULT" );
	set ( "SET_CHASE_ENEMIES", "true" );
	set ( "SET_LOOK_FOR_ENEMIES", "true" );
	set ( "SET_IGNOREALERTS", "false" );
	set ( "SET_WALKING", "true" );
	set ( "SET_RUNNING", "false" );
	wait ( 4000.000 );

	task ( "ranWalk1" )
	{
		set ( "SET_NAVGOAL", "wpoint1" );
	}
	task ( "ranWalk2" )
	{
		set ( "SET_NAVGOAL", "wpoint2" );
	}
	task ( "ranWalk3" )
	{
		set ( "SET_NAVGOAL", "wpoint3" );
	}
	loop ( -1 )
	{
		if ( random ( 0, 3 ) > 2 )
		{
			do ( "ranWalk3" );
			wait ( "ranWalk3" );
		}
		else ()
		{
			if ( random ( 0, 3 ) > 1 )
			{
				do ( "ranWalk2" );
				wait ( "ranWalk2" );
			}
			else ()
			{
				if ( random ( 0, 3 ) > -1 )
				{
					do ( "ranWalk1" );
					wait ( "ranWalk1" );
				}
			}
		}
	}
}
All three navgoals are accessible with the script, and the failure is completely spontaneous, with no apparent logical cause. There's no pattern to it. After a random interval the engine fails to run the script. It seems the SET_NAVGOAL related function either misfires a successful return too early, or fails to send a return at all, and causes the script to hang, waiting forever for the SET_NAVGOAL task to finish.
Link to comment

The type of AI that you want is referred to as 'sandboxing' and is common in a lot of Bethesda games. Let's take a simple shopkeeper AI (LeoStahl from Fallout 3 is a good example):

 

* Between X - X ('game time') he hangs out at his restaurant, doing small tasks but mostly just standing around

* Between Y - Y he goes to the saloon and has a drink

* He has a bit of a nasty...um...habit. He goes to the Water Treatment Plant at Z-Z to shoot up.

* Lastly, he goes to bed and the cycle repeats.

 

It's not so much random as you think, it's more of a patrol on a loop. But unless the player is really paying attention, they won't notice it. I think in your case, the sandboxing for an AI can look like:

* Meet with friends at one of three random locations and chat with them.

* Go to Class 1 and sit

* Go to Class 2 and sit

* ....

* repeat

 

I don't really know about the waypointing in JA tbh, but I remember it to be about as finnicky as you describe.

Cerez likes this
Link to comment

Yes, exactly. I was hoping to randomise that behaviour a little bit as well by giving the NPC a few possible activities to choose from. That way even if the player follows them, they may not do the same thing they did last time (yesterday).

 

I was hoping I could script in detail an interactive living simulation environment for the Jedi Temple on Coruscant, but unfortunately JKA has disappointed me in this regard. It just doesn't have what it takes to make it happen... Too unstable, too unreliable, too buggy... :(

 

It's a big letdown in modding, to be honest. For the first time I really feel the game's limits.

 

Edit:

 

Would be nice to find out what's happening code-side with that SET_NAVGOAL timeout/misfire, though...

Link to comment

Protip: turn on /developer 1. I'm guaranteeing you that it will complain about something.

I was hopeful this would show something, but nope... No message received when the script fails to continue running. Apparently the game thinks everything's okay. Makes sense, considering that it never realises that the navgoal walk function had finished, but not returned successfully.

 

Based on careful observation, I'm pretty sure this is what's happening:

 

1. The navgoal is set and the character starts walking to navgoal.

2. The wait for the task containing the navgoal function for some reason ends abruptly, and a second navgoal setting is superimposed on the original process -- here lies the bug.

3. This breaks the loop cycle, causing one of the tasks to never return successfully, even when the NPC reaches the navgoal.

 

It's quite a strange bug, really. But occasionally you can see the character change navgoals halfway through the path, walking between them -- which, if you have a look at my script, is quite impossible, and shouldn't be happening. That's how I know it's definitely something on the code-side going wrong, and a second navgoal task firing while the first one has still not finished (superimposed).

Link to comment

Put a wait() at the beginning (or end) of the loop then. If that fixes it, then you're right.

Tried it, but this only causes the script to hang the first time the loop runs, waiting for the other two tasks (that didn't run) to finish. There's really no other place for me to put the waits, script-wise.

 

It's more likely an issue with your setup. I wouldn't know though, as you haven't shown it.

This is my current setup:

 

{
"classname" "NPC_spawner"
"origin" "1139 -3261 455"
"NPC_type" "ahsoka"
"spawnflags" "32"
"angle" "71"
"npc_targetname" "walker"
"spawnscript" "walker"
}
{
"classname" "waypoint_navgoal"
"origin" "139 -3652 455"
"targetname" "wpoint1"
}
{
"classname" "waypoint"
"origin" "125 -3573 455"
"target" "wpoint2"
"target2" "wpoint3"
}
{
"classname" "waypoint_navgoal"
"origin" "1239 -3361 455"
"targetname" "wpoint2"
}
{
"classname" "waypoint"
"origin" "1183 -3358 455"
"target" "wpoint3"
"target2" "wpoint1"
}
{
"classname" "waypoint_navgoal"
"origin" "-812 -3268 455"
"targetname" "wpoint3"
}
{
"classname" "waypoint"
"origin" "-733 -3271 455"
"target" "wpoint2"
"target2" "wpoint1"
}
At one point I had added the waypoint targets to the navgoals as well, just to make sure that it wasn't the lack of that link that was breaking the walk cycle. It wasn't. As you said, the targets on the navgoals are optional, really, as long as you have the properly targeted waypoints next to them.
Link to comment

Hmm... explain me this. The following script will make the character walk to wpoint1, then wpoint3, and then stop:

 

rem ( "Random Walker Test Script" );

affect ( "walker", FLUSH )
{
	set ( "SET_WEAPON", "WP_NONE" );
	set ( "SET_PLAYER_TEAM", "TEAM_PLAYER" );
	set ( "SET_ENEMY_TEAM", "TEAM_ENEMY" );
	set ( "SET_BEHAVIOR_STATE", "BS_DEFAULT" );
	set ( "SET_CHASE_ENEMIES", "true" );
	set ( "SET_LOOK_FOR_ENEMIES", "true" );
	set ( "SET_IGNOREALERTS", "false" );
	set ( "SET_WALKING", "true" );
	set ( "SET_RUNNING", "false" );
	wait ( 4000.000 );

	task ( "ranWalk1" )
	{
		set ( "SET_NAVGOAL", "wpoint1" );
	}
	task ( "ranWalk2" )
	{
		set ( "SET_NAVGOAL", "wpoint2" );
	}
	task ( "ranWalk3" )
	{
		set ( "SET_NAVGOAL", "wpoint3" );
	}
	declare ( FLOAT, "ranNum");
	set ( "ranNum", 3 );
	loop ( -1 )
	{
		if ( get ( FLOAT, "ranNum" ) > 2 )
		{
			do ( "ranWalk3" );
			wait ( "ranWalk3" );
			set ( "ranNum", 2 );
		}
		else ()
		{
			if ( get ( FLOAT, "ranNum" ) > 1 )
			{
				do ( "ranWalk2" );
				wait ( "ranWalk2" );
				set ( "ranNum", 1 );
			}
			else ()
			{
				if ( get ( FLOAT, "ranNum" ) > -1 )
				{
					do ( "ranWalk1" );
					wait ( "ranWalk1" );
					set ( "ranNum", 3 );
				}
			}
		}
	}
}
How does that work? o.O Where the hell is the game getting these instructions from?
Link to comment

Those are not numbers. Those are the entities, and it contains all the information about the setup you've asked for.

 

I'm not working with a MAP file. I'm working with a BSP, and using ENT modding to add the waypoints and other entities needed.

 

I've provided a screenshot before (the last one). The same screenshot applies. I've only moved the stairs navgoal down to ground level.

 

As for dowait, dowait is actually do wait. It's just a shorthand for it. IBIze (the compiler) turns it into a do wait pair when you compile the script. So whether you write a do wait pair or the shorthand dowait makes to difference in the final script that gets executed. It's always a do wait pair in the end.

Link to comment

Fair enough, but you can take my word for it -- they are above the floor, at the right level (and exactly the same height), and there is not a single obstacle between the three navgoals. It's a flat surface where the three navgoals (and their close waypoint companions) are laid out like this:

 

      o
      |
o-         -o
For the sake of the experiment, I tried to make it as straightforward as possible -- and it still fails, hehh! >.<'
Link to comment

Is there a waypoint in the middle of that trifecta, as I'll call it?

No, there isn't. Should there be? How should I hook up the mid-waypoint?

 

Edit:

 

Well, I've added a fourth, mid waypoint, hooking it up this way:

 

{
"classname" "waypoint"
"origin" "255 -3276 455"
"target" "wpoint1"
"target2" "wpoint2"
"target3" "wpoint3"
}
      o
      |
o-    -     -o
But it made no difference in the NPC's behaviour whatsoever. And once again, I've noticed the NPC switch waypoint_navgoals in the middle of a walk.
Link to comment

It's because you are not waiting at all for the NPC to finish walking. You need to wait a certain amount of time (even after the do/wait) for the NPC to finish walking.

Here is 4_point_patrol.ibi, a Raven script, decompiled by DEvaheb:

// Generated by DEvaheb v1.0
// Decompiled from file "C:\Program Files (x86)\Steam\steamapps\common\Jedi Academy\GameData\base\4_nav_wander.ibi"


task ( "nav_patrol1" )
{
    set ( "SET_NAVGOAL", $get( STRING, "SET_PARM1" )$ );
}


task ( "nav_patrol2" )
{
    set ( "SET_NAVGOAL", $get( STRING, "SET_PARM2" )$ );
}


task ( "nav_patrol3" )
{
    set ( "SET_NAVGOAL", $get( STRING, "SET_PARM3" )$ );
}


task ( "nav_patrol4" )
{
    set ( "SET_NAVGOAL", $get( STRING, "SET_PARM4" )$ );
}

do ( "nav_patrol1" );
wait ( "nav_patrol1" );
wait ( $get( FLOAT, "SET_PARM5" )$ );
do ( "nav_patrol2" );
wait ( "nav_patrol2" );
wait ( $get( FLOAT, "SET_PARM5" )$ );
do ( "nav_patrol3" );
wait ( "nav_patrol3" );
wait ( $get( FLOAT, "SET_PARM5" )$ );
do ( "nav_patrol4" );
wait ( "nav_patrol4" );
wait ( $get( FLOAT, "SET_PARM5" )$ );
set ( "SET_BEHAVIOR_STATE", "BS_WANDER" );

This script takes 5 parameters from parm1/parm2/...:

- parm1/2/3/4 are targetnames for patrol points

- parm5 is how long to wait for the NPC to walk to each point

Link to comment

I begin to have a serious suspect... emmm... the openJK actual version support the AI of walking NPC  , if waypoints are not into the maps, but they're added throught ent modding? D:

@@Cerez try to make the same script running in a simply one room testmap when you recreate the same waypoint, NPC \ player, cinematic and script condition. if at parity of condition, into a map-bsp file it works, should be a problem of interface about entmodding, openjk e coded nav system.

D:

 

mmm , the eez'script should work. try it before.

Link to comment

Is this (npc walking around the map) achievable in mp? @@eezstreet

 

Before I had problems with ibi scripts(server crashes, I was using retail jampserver though l so I'm not sure about it (currently using ojkded)

I am hosting Jedi Outcast and Jedi Academy servers for free up to 8 servers. Contact me if you are in need of a server for your community. 🙂

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...