action PlayarTest01_Wizard_Walk()
{
//---------------------------------
// events
my.event = PlayarTest01_Wizard_Hit;
my.emask |= ENABLE_IMPACT;
// wait(3);
// printf("player init");
//---------------------------------
// set z always by c_tracing
VECTOR vFeet;
vec_for_min(vFeet,me);
vec_mul(vFeet,my.scale_x);
c_trace(vector(my.x, my.y, 5000.0), vector(my.x, my.y, -1000.0), IGNORE_ME | IGNORE_CONTENT | IGNORE_PASSABLE | USE_POLYGON | USE_BOX); // | USE_BOX for smoother ground detection
if (HIT_TARGET)
{
my.z = hit.z - vFeet.z;
}
//---------------------------------
// boundary box
wait(1);
my.eflags |= FAT | NARROW; // set both flags to prevent automatic recalculation on scale changes
vec_set(my.min_x,vector(-8,-8, -3)); // better step if xy are lower and z is higher - but worse small wall detection
vec_set(my.max_x,vector(16, 8, 32)); // better step if x is lower
// vec_set(my.max_x,vector(25,8,30)); // no wall penetration
wait(1);
//---------------------------------
// material settings
my.ambient = 12; // 0..100, 10 = 25.5 in 0..255
// my.material = mtl_model;
// normalmapped
playermat = mtl_create();
vec_set(playermat.ambient_blue, mat_model.ambient_blue);
vec_set(playermat.diffuse_blue, mat_model.diffuse_blue);
vec_set(playermat.specular_blue, mat_model.specular_blue);
vec_set(playermat.emissive_blue, mat_model.emissive_blue);
playermat.power = mat_model.power;
playermat.albedo = mat_model.albedo;
effect_load(playermat, "sc_obj_modelN_MB.fx"); // the correct normal mapping shader okay with scsm or without
my.material = playermat;
//---------------------------------
// flags
// set FLAG2 to make the wizard detectable by c_scan,
// and store the wizard pointer in its own CREATOR skill
// so that the detecting entity knows its enemy
set(my, FLAG2 | SHADOW);
my.CREATOR = me;
my.STATE = 1;
// printf("player ready");
//---------------------------------
var distance = 0;
var jump_in_progress = 0;
var actual_gravity = 0;
while (UIMode==(var)UIMODE_PLAYTEST01)
{
//-----------------------------------------------------------
// state 1: walking
if (my.STATE == 1)
{
//-----------------------------------------------------------
my.ANIMATION %= 100;
//-----------------------------------------------------------
// rotate the entity with the arrow keys
if ((window_focus) && (mouse_valid))
{
my.pan += (key_a-key_d)*5*time_step;
// // or rotate with collision to avoid going through polygon thin walls at mesh borders
// var rot_angle = (key_a-key_d)*5*time_step;
// c_rotate(me, vector(rot_angle, 0, 0), IGNORE_PASSABLE);
}
//-----------------------------------------------------------
// move the entity forward/backward with the arrow keys
if (jump_in_progress == (var)0) // keep previous distance during jump
{
distance = 0;
if ((window_focus) && (mouse_valid))
{
distance = (key_w-key_s) * time_step;
if ((key_shift) && (distance > 0)) // only forward
{
distance *= play01_runspeed;
}
else if ((key_ctrl) && (distance != (var)0)) // moving
{
distance *= play01_crawlspeed;
}
else
{
distance *= play01_walkspeed;
}
if (key_ctrl)
{
// smaller bbox
vec_set(my.min_x,vector(-8,-8, -12));
vec_set(my.max_x,vector(16, 8, 20));
}
else
{
// standard bbox
vec_set(my.min_x,vector(-8,-8, -3));
vec_set(my.max_x,vector(16, 8, 32));
}
}
}
// simple move
// c_move(me, vector(distance,0,0), NULL, GLIDE | IGNORE_PASSABLE );
//-----------------------------------------------------------
// prevent under water movement
VECTOR temp_vec;
vec_set(temp_vec, vector(distance, 0, 0));
vec_rotate(temp_vec, my.pan);
vec_add(temp_vec, my.x);
VECTOR temp2_vec;
vec_set(temp2_vec, vector(temp_vec.x, temp_vec.y, temp_vec.z - 1000.0));
c_trace(temp_vec, temp2_vec, IGNORE_ME | IGNORE_PASSABLE | USE_POLYGON); // | USE_BOX for smoother ground detection
var water_hit = -1000;
if (HIT_TARGET)
{
water_hit = hit.z;
}
#ifdef PLAY01_DEBUG
// debug - ok
draw_line3d(temp_vec, NULL, 100);
draw_line3d(temp2_vec, COLOR_WHITE, 100);
#endif
//-----------------------------------------------------------
// allow no bad collision with small polygon models
vec_set(temp_vec, vector(my.max_x*sign(distance),0,0)); // *sign(distance) needed to check forward or backward move
vec_rotate(temp_vec, my.pan);
vec_add(temp_vec, my.x);
temp_vec.z += my.min_z;
// vec_set(temp2_vec, vector(my.x, my.y, my.z+my.min_z));
vec_set(temp2_vec, vector(my.min_x*sign(distance),0,0)); // *sign(distance) needed to check forward or backward move
vec_rotate(temp2_vec, my.pan);
vec_add(temp2_vec, my.x);
temp2_vec.z += my.min_z;
var polygon_hit = c_trace(temp2_vec, temp_vec, IGNORE_ME | IGNORE_PASSABLE | USE_POLYGON);
#ifdef PLAY01_DEBUG
// debug - ok
draw_line3d(temp_vec, NULL, 100);
draw_line3d(temp2_vec, COLOR_RED, 100);
#endif
//-----------------------------------------------------------
// gravity
var move_z = 0;
// ground
var grounddist = c_trace(my.x, vector(my.x, my.y, my.z-10000), IGNORE_ME | IGNORE_PASSABLE);
// acceleration - if ground is lower or jumping
if((grounddist + vFeet.z > 0) || (actual_gravity < 0))
{
actual_gravity += play01_gravity_force * time_step;
// apply acceleration
move_z -= minv(actual_gravity * time_step, grounddist + vFeet.z);
}
else
{
actual_gravity = 0;
move_z = (hit.z - vFeet.z) - my.z;
// move_z -= grounddist + vFeet.z;
}
// jump by acceleration
if ((window_focus) && (mouse_valid))
{
if(key_space)
{
// allow jump
if(grounddist + vFeet.z - minv(actual_gravity * time_step, grounddist + vFeet.z) == (var)0)
{
actual_gravity = -play01_jumpspeed;
jump_in_progress = 1;
}
}
}
my.z += move_z;
//-----------------------------------------------------------
// do move if allowed
if (
(water_hit > -GetMapTileSize())
&&
(
(polygon_hit > (var)GetMapTileSize() * 0.71) // polygone detection HIT_TARGET and it is far enough
||
(polygon_hit <= (var)0) // no polygon detection HIT_TARGET
)
)
{
c_move(me, vector(distance,0,0), nullvector, IGNORE_PASSABLE); // | USE_POLYGON | GLIDE
}
//-----------------------------------------------------------
// adjust entity to the ground height, using a downwards trace
// c_trace(my.x, vector(my.x, my.y, my.z-1000), IGNORE_ME | IGNORE_PASSABLE);
// my.z = hit.z - vFeet.z; // always place player's feet on the ground
// // smoother on-stairs movement, slower (but still ugly) falling - some underground placement errors... XXX
// c_trace(vector(my.x, my.y, my.z), vector(my.x, my.y, my.z - 1000.0), IGNORE_ME | IGNORE_PASSABLE); // | USE_BOX for smoother ground detection
// if (HIT_TARGET)
// {
// my.z = smooth(hit.z - vFeet.z, 0.50);
// }
//-----------------------------------------------------------
// animate the entity
// my.ANIMATION += 2*distance;
// ent_animate(me,"walk",my.ANIMATION,ANM_CYCLE);
var anim = sign(distance); // forward or backward move
ent_animate(me,NULL,0,0); // reset all bones
if (jump_in_progress) // jump
{
my.ANIMATION += 7*time_step;
ent_animate(me, "jump", my.ANIMATION, NULL);
if (my.ANIMATION >= (var)100)
{
jump_in_progress = 0;
my.ANIMATION %= 100;
}
}
else if ((key_shift) && (anim)) // run
{
my.ANIMATION += 10*time_step*anim;
ent_animate(me, "run", my.ANIMATION, ANM_CYCLE);
my.ANIMATION %= 100;
}
else if ((key_ctrl) && (anim)) // crawl, move
{
my.ANIMATION += 4*time_step*anim;
ent_animate(me, "crawl", my.ANIMATION, ANM_CYCLE);
my.ANIMATION %= 100;
}
else if ((key_ctrl) && (!anim)) // crawl, no move
{
ent_animate(me, "crawl", my.ANIMATION, NULL);
}
else if (anim) // walk
{
my.ANIMATION += 10*time_step*anim;
ent_animate(me, "walk", my.ANIMATION, ANM_CYCLE);
my.ANIMATION %= 100;
}
else // no move, no jump, no crawl
{
my.ANIMATION += 3*time_step;
ent_animate(me, "lstand", my.ANIMATION, ANM_CYCLE);
my.ANIMATION %= 100;
}
ent_animate(me, "wpose", my.ANIMATION, ANM_ADD);
//-----------------------------------------------------------
// key e pressed -> go to state 2
if ((key_e) && ((window_focus) && (mouse_valid)))
{
my.ANIMATION = 0;
my.STATE = 2;
}
//-----------------------------------------------------------
}
//-----------------------------------------------------------
//-----------------------------------------------------------
// state 2: casting a spell
if (my.STATE == 2)
{
// my.ANIMATION += 8*time_step;
// ent_animate(me,"attack",my.ANIMATION,0);
//
// if (my.ANIMATION > 100)
{ // create the spell and go to state 3
// ent_create("spell.mdl",vector(my.x,my.y,my.z+20), PlayarTest01_Spell_Fly);
VECTOR vGunEnd;
vec_for_vertex(vGunEnd,my,5035);
ent_create("spell.mdl",vGunEnd, PlayarTest01_Spell_Fly);
my.ANIMATION = 0;
my.STATE = 3;
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
// state 3: waiting for key release
if (my.STATE == 3)
{
if (!key_e)
{
// my.ANIMATION += 3*time_step;
// ent_animate(me,NULL,0,0);
// ent_animate(me,"lstand",my.ANIMATION,0);
// ent_animate(me,"reload",my.ANIMATION,ANM_ADD);
//
// // my.ANIMATION += 8*time_step;
// // ent_animate(me,"reload",my.ANIMATION,0);
//
// if (my.ANIMATION > 100)
my.STATE = 1; // when key was released, back to state 1
}
// my.STATE = 1; // fast shooting test
}
//-----------------------------------------------------------
//-----------------------------------------------------------
// state 4: death animation
if (my.STATE == 4)
{
play01_winner = 2; // other wizard won
my.ANIMATION += 3*time_step;
ent_animate(me,"death",my.ANIMATION,0);
if (my.ANIMATION > 70)
return;
}
//-----------------------------------------------------------
//-----------------------------------------------------------
// // create decal as shadow
// c_trace(my.x,vector(my.x,my.y,my.z-100) , IGNORE_ME | IGNORE_CONTENT | IGNORE_PASSABLE | IGNORE_FLAG2 | IGNORE_SPRITES | SCAN_TEXTURE );
// if (HIT_TARGET)
// {
// PARTICLE* shadow_p = ent_decal(you,shadow_bmp,(abs(me.max_x)+abs(me.max_y)+abs(me.max_z)),0); // A7
// shadow_p.material = mtl_decalshadow; // assign another material when contact material is not suitable for decals like terraintex.fx
// set(shadow_p,TRANSLUCENT);
// shadow_p.alpha = 50;
// shadow_p.lifespan = 0.01;
// }
//-----------------------------------------------------------
PlayarTest01_Camera_Follow(me); // own camera
wait(1);
}
}