29.05.06 okay. today as promised the movementcode. please note that this is the code i currently use. it will not work if you copy and paste it to your projects. however you may study it to see how it works for me.

in short, i move the player at the host with ent_move and send positions with send_skill using SEND_RATE 4times a second to the client. the client then interpolates between the positions. the interpolation code is very similar to those william posted in this thread.

the skelleton of the code is similar to locoweeds tutorial.

the project is coming along niceley. right now i tested a simple inventory code so players both the client and host can pick up items dropped by npcs or other players. i do this by first creating an item with ent_create giving it an item_id wich defines wich item it is. then i make it sensitive for click. if its clicked at the client i set the skill ._player_number_wants_to_pick_me_up to the playernumber of the player who clicked it and send this skill to the server. the server then puts this item in the inventory skill slot of the player and sends back that its done to all players!

next things iam gonna do is making this work with movable panels so players can drop items with the mouse once they are in the inventory.

but heres the movement code i promised, have fun with it! note: it may not be perfectly clean or bugfree, please let me know if you find some majore mistakes. thx

Code:


// sets all nosends, because setting my.nosend = on causes problems in 6.4.x
function set_nosend()
{
my.nosend_frame = on; my.nosend_alpha = on; my.nosend_ambient = on; my.nosend_color = on; my.nosend_light = on; my.nosend_uv = on;
my.nosend_origin = on; my.nosend_angles = on; my.nosend_flags = on; my.nosend_scale = on; my.nosend_skin = on; my.nosend_sound = on;
}



// function for player events on the server
function real_player_event()
{

// client disconnected
if (EVENT_TYPE == EVENT_DISCONNECT)
{
// do this to keep the number of players in order
gl_number_of_players -= 1; // decrement number of players

// go through all entities, any player # that was above mine, decrement his player number
you = ent_next(NULL);
while(you != NULL)
{
if(you._player_number > my._player_number)
{
you._player_number -= 1;
send_skill(you._player_number, SEND_ALL);
}
you = ent_next(you);
}

send_var(gl_number_of_players); // let everyone know new number of players
ent_remove(me); // remove ent of player that quit
}
if (EVENT_TYPE == EVENT_CLICK)
{

}
IF (EVENT_TYPE == EVENT_TOUCH) {
MY.LIGHT = ON;
MY.RED = 255;
MY.GREEN = 0;
MY.BLUE = 0;
RETURN;
}
IF (EVENT_TYPE == EVENT_RELEASE) {
MY.LIGHT = OFF;
RETURN;
}



}

// event handler for clients
function real_player_local_event()
{
if (EVENT_TYPE == EVENT_CLICK)
{

}
IF (EVENT_TYPE == EVENT_TOUCH) {
MY.LIGHT = ON;
MY.RED = 255;
MY.GREEN = 0;
MY.BLUE = 0;
RETURN;
}
IF (EVENT_TYPE == EVENT_RELEASE) {
MY.LIGHT = OFF;
RETURN;
}


}

// local entity function for getting click and so on
action real_player_local()
{

my.invisible = on;
sleep(1);


// get faction and send to server but only for the own player instance
if(me == player)
{
my._faction = id_faction;
send_skill(my._faction, 0);
my._race = id_race;
send_skill(my._race, 0);
}

var calc_angle[3];
var move[3];
var move_old[3];
var length; // range from real to target pos
var vecfrom[3]; // temp
var vecto[3]; // temp
var temp_loc[3]; // temp

my.enable_click = on;
my.enable_touch = on;
my.enable_release = on;


my.event = real_player_local_event;

my.passable = on;


// do this to assure players are in mode_stand at start
my._receive_x = my.x;
my._receive_y = my.y;
my._receive_z = 1;
// trace to geht right height to terrain
vecFrom.x =my.x;
vecFrom.y =my.y;
vecFrom.z = 200;

vec_set(vecTo,VecFrom);
vecTo.z = -200;

c_trace(vecFrom,vecTo, IGNORE_ME|IGNORE_PASSABLE|IGNORE_CONTENT|IGNORE_SPRITES|USE_POLYGON);
vec_set(temp_loc,vecTo);
my.z = target.z + 32;

// start animation loop
animate();

// intially set animation to stand, this will be changed below if necessary
my._animation_state = animation_state_STAND;

my.invisible = off;

sleep(1); // fix for bug when players didnt move
my._mode = mode_stand;

while(1)
{
my._prev_anim_state = my._animation_state; // save animation state

//stand
if(my._mode == mode_stand)
{
my._animation_state = animation_state_STAND;

// new different hostposition incoming -> go move there
if(my._receive_z == 0)
{
my._disttotarget = abs(my.x - my._receive_x) + abs(my.y - my._receive_y);
if(my._disttotarget >= 35)
{
my._mode = mode_walk;
}
}
}

// moving
if(my._mode == mode_walk)
{
my._animation_state = animation_state_WALK;

my._disttotarget = abs(my.x - my._receive_x) + abs(my.y - my._receive_y);

if (my._disttotarget >= 12)
{
// interpolate movement
vec_set(move.x, my._receive_x);

if(move_old.x != move.x)
{
vec_set(length.x, move.x);
vec_sub(length.x, my.x);
vec_set(temp.x, move.x);
vec_sub(temp.x, my.x);
vec_to_angle(calc_angle.pan, temp.x);
}

vec_normalize(length, 1);


my.x += length.x * (my._movespeed -0.8 ) * time;
my.y += length.y * (my._movespeed -0.8 ) * time;
vec_set(temp.x, nullvector);

vec_set(move_old.x, my._receive_x);

// turn
if((my.pan < calc_angle.pan + 10) || (my.pan > calc_angle.pan - 10))
{
my.pan = my.pan + ang(calc_angle.pan-my.pan) * 0.5 * time ;//i am turning
}
}
// prevent stopping
if ((my._disttotarget <12) && (my._receive_z == 0))
{
my.x += length.x * (my._movespeed -1 ) * time;
my.y += length.y * (my._movespeed -1 ) * time;
}


// trace to geht right height to terrain
vecFrom.x =my.x;
vecFrom.y =my.y;
vecFrom.z = 200;

vec_set(vecTo,VecFrom);
vecTo.z = -200;

c_trace(vecFrom,vecTo, IGNORE_ME|IGNORE_PASSABLE|IGNORE_CONTENT|IGNORE_SPRITES|USE_POLYGON);
vec_set(temp_loc,vecTo);
my.z = target.z + 32;

// are we near the last received hostposition? and z is 1
if ((my._disttotarget < 12) && (my._receive_z == 1))
{
my._mode = mode_stand;
}

}

wait(1);
}


}


// action for the player is run at the server
action real_player
{


my.invisible = on; // set this so others dont see me until created

var dire[3]; // turn to angle
var vecfrom[3]; // temp
var vecto[3]; // temp
var temp_loc[3]; // temp


sleep(1); // this fixes the problem where some players dont receive data
proc_local(my, real_player_local); // function for client




my.enable_disconnect = on;
my.event = real_player_event; // event function for server

// server gives the players entity his player number
gl_number_of_players += 1; // after entity created increment number of players ingame
send_var(gl_number_of_players); // send this new number to all connected people

my._player_number = gl_number_of_players; // set the player number to the skill


// this code is to solve high latency creation problem
sleep(.3); // this can be left at .3 no matter what
ent_sendnow(my);
sleep(.3); // sleep(3); // high latency solution for now

set_nosend(); // dont send any automatic updates

my.enable_click = on;
my.enable_touch = on;
my.enable_release = on;
my.passable = on;






// set faction and race for host
if(connection == 3 && me == player)
{
my._faction = id_faction;
my._race = id_race;
}

// wait for faction and race if client
while((!my._faction) && (!my._race)) {wait(1);}
send_skill(my._faction, SEND_ALL);

if(my._race == RACE_HUMAN_MALE)
{
my._health = HEALTH_HUMAN;
my._mana = MANA_HUMAN;
my._movespeed = 8;
}

if(my._race == RACE_ORC_MALE)
{
my._health = HEALTH_ORC;
my._mana = MANA_ORC;
my._movespeed = 13;
}


// send entity skills of already ingame players
you = ent_next(NULL);
while(you != NULL)
{
if(you._movespeed)
{
send_skill(you._movespeed, SEND_ALL); // send the movespeed so others can move my entity
}
if(you._player_number)
{
send_skill(you._player_number, SEND_ALL); // send my player number skill to all players
}
if(you._faction)
{
send_skill(you._faction, SEND_ALL); // send my faction id skill to all players
}
if(you._health)
{
send_skill(you._health, SEND_ALL); // send health skill to all players
}
if(you._mana)
{
send_skill(you._mana, SEND_ALL); // send my mana skill to all players
}
if(you._race)
{
send_skill(you._race, SEND_ALL); // send my race skill to all players
}

// send position and mode also for right start positions
send_skill(you.x, SEND_ALL);
send_skill(you.y, SEND_ALL);
send_skill(you._mode, SEND_ALL);


you = ent_next(you);
}



// set initial target coordinates so entity doesnt start moving to nullvector at start
my._target_x = my.x;
my._target_y = my.y;

// start animation loop for host
animate();

my._mode = mode_stand; // starting mode

// intially set animation to stand, this will be changed below if necessary
my._animation_state = animation_state_STAND;


// trace to geht right height to terrain
vecFrom.x = my.x;
vecFrom.y = my.y;
vecFrom.z = 200;

vec_set(vecTo,VecFrom);
vecTo.z = -200;

c_trace(vecFrom,vecTo, IGNORE_ME|IGNORE_PASSABLE|IGNORE_CONTENT|IGNORE_SPRITES|USE_POLYGON|GLIDE);
vec_set(temp_loc,vecTo);
my.z = target.z + 32;

my.invisible = off;
while(1)
{


my._prev_anim_state = my._animation_state; // save animation state
//stand
if(my._mode == mode_stand)
{
my._animation_state = animation_state_STAND;
my._receive_z = 0;
if(abs(my.x - my._target_x) + abs(my.y - my._target_y) > 20)
{
my._mode = mode_walk;
}
}
//move to location stored in my.target_x
if(my._mode == mode_walk)
{
my._animation_state = animation_state_WALK;
my.tilt = 0; // we only need the correct "pan" angle, not tilt


while (abs(my.x - my._target_x) + abs(my.y - my._target_y) > 15 ) // stop near the target
{
// turn
vec_set(temp.x, my._target_x);
vec_sub(temp.x, my.x);
vec_to_angle(dire.pan, temp.x);

if((my.pan < dire.pan + 10) || (my.pan > dire.pan - 10) )
{
my.pan = my.pan + ang(dire.pan-my.pan) * 0.5 * time;//i am turning
}

// move
vec_diff(temp.x, my.x, my._target_x);
vec_normalize(temp.x,- my._movespeed * time);

// ent_move cause its 20x faster
move_mode = glide+ignore_me+ignore_you+ignore_sprites+ignore_passable;
ent_move(nullvector, temp.x);
//c_move(my, nullvector, temp.x, glide|ignore_me|ignore_you|IGNORE_CONTENT|ignore_sprites|ignore_passable );

// trace to geht right height to terrain
vecFrom.x = my.x;
vecFrom.y = my.y;
vecFrom.z = 200;

vec_set(vecTo,VecFrom);
vecTo.z = -200;

c_trace(vecFrom,vecTo, IGNORE_ME|IGNORE_PASSABLE|IGNORE_CONTENT|IGNORE_SPRITES|USE_POLYGON|GLIDE);
vec_set(temp_loc,vecTo);
my.z = target.z + 32;

// send current position to other clients
vec_set(my._receive_x, my.x);
my._receive_z = 0;
send_skill(my._receive_x, SEND_ALL | SEND_VEC | SEND_RATE | SEND_UNRELIABLE);


wait (1);
}

// switch back to standing
my._mode = mode_stand;
vec_set(my._receive_x, my.x);
// z = 1 indicates stop of movement
my._receive_z = 1;
send_skill(my._receive_z, SEND_ALL | SEND_VEC );
wait(1);

}
wait (1);

}

}



// function create_player() create a player at spawnpoint
function create_player()
{

if (id_race == RACE_HUMAN_MALE )
{
player = ent_create(str_cbabe,vector(100,300,0),real_player);
while(!player) {wait(1);}
}
if (id_race == RACE_ORC_MALE )
{
player = ent_create(str_warlock,vector(100,100,0),real_player);
while(!player) {wait(1);}
}


}



// set the race to human
function set_race_human()
{
id_race = RACE_HUMAN_MALE;
cl_race_not_set = FALSE;
}

// set the race to orc
function set_race_orc()
{
id_race = RACE_ORC_MALE;
cl_race_not_set = FALSE;
}

// set the race to woodelv
function set_race_woodelv()
{
id_race = RACE_HUMAN_MALE;
cl_race_not_set = FALSE;
}



Last edited by ulf; 05/29/06 12:08.