how to grab a ledge?

Posted By: birkin

how to grab a ledge? - 07/15/08 12:47

hi,

i am working on a 3rd person game like zelda or something else.
and if have the problem that i have no idea how i can create a function for grabbing ledges. i have searched for a tutorial for this, but i donīt find something helpful. if some can explain me how, or send me a code for this, it would be great^^...
thx.
Posted By: bstudio

Re: how to grab a ledge? - 07/17/08 12:03

I think there was a zelda style movement contribution which also featured grabbing ledges (I hope my memory serves me right here). You can study that and implement it in your project
Posted By: gri

Re: how to grab a ledge? - 07/17/08 12:18


yes there was a early A5 project with some good design documents too.
It was like Thomb Raider and "cliffhanging" was included.

I dont know the exact name after so long time, but it was:

"***** - the young sorceress"


,gri
Posted By: TigerTao

Re: how to grab a ledge? - 07/17/08 12:32

One simple way is to use c_trace

What you need to do is to trace a small way from a point on the player where the hands of the grabbing animation should be(way above his head usually)

When you go up to a low wall and check the c_trace it should give you the distance to the wall.

When you jump, the c_trace distance will dramatically change if it passes over the top of the wall. It should return a 0 as the trace hits nothing as it only traces a small distance.

Use this as a basic indicator to then tell your character that he is at the top of a wall and then stop his gravity/ z movement so he hangs there.

One other thing is to rotate the player to the ledge so that the hanging animation fits to the rotation of the ledge.
Posted By: TigerTao

Re: how to grab a ledge? - 07/17/08 19:52

I was going to put up my old wall hangng code but it really is as simple as I described above. Here it is anyway heavily edited down but what you need is here

Code:
vec_set(wall_finder.x,vector(200,0,26));//26 being the position of my hands in wall hanging animation
vec_rotate(wall_finder.x,my.pan);
vec_add(wall_finder.x,my.x);  
vec_set(from_player.x,vector(0,0,26)); 
vec_rotate(from_player.x,my.pan);	
vec_add(from_player.x,my.x); 
wall_distance = c_trace(from_player.x,wall_finder.x,use_box | ignore_me | ignore_passable);

IF(wall_distance == 0)//define this further so it does not work when on ground and only up against a wall,eg, when jumping and wall_distance previously was != 0
{
gravity_on = 0;//condition for gravity to work when at 1
current_speed = 0;//my forward motion stopped
//now play wall hanging animation here
}



The only difficult part is rotating the player to the wall

Here is the code for doing that
Code:
vec_set(wall_angle_finder.x,vector(200,0,0));//create a vector to trace 200 quants to in front of player 
vec_rotate(wall_angle_finder.x,my.pan);//rotate it to the rotation of the player
vec_add(wall_angle_finder.x,vector(my.x,my.y,my.z));//add it to the position of the player
find_wall_angle = c_trace(my.x,wall_angle_finder.x,use_box | ignore_me | ignore_passable);//trace 200 quants in front of player 	
vec_set(wallNormal, normal);//set wallNormal to the returned normal vector of the wall	 				 				 		
vec_to_angle(wallNormal, wallNormal);//convert the vector to its angle			
wallNormal.pan += 180;//swing it around to point away from player, normals point out of a wall, we want it pointing in			
wall_degrees = ang(wallNormal.pan - my.pan);	//find the angle difference between the normal and the player	


Now use wall_degrees to rotate your character to face the wall
Posted By: Havoc22

Re: how to grab a ledge? - 07/17/08 20:28

You should take a look at that axys demo I believe it was called. I don't know if it is open source anymore, but it was open to view the code at one point in a demo. It was a 2d scroller, but it had ledge climbing and all of that worked out in it. I think I still have the demo because I was also interested in ledge climbing and tracked it down. It should probably work the same in a 3d environment but I'm not sure.

Either way good luck, you may have figured it out already from these earlier posts.
Posted By: MDMDFSS

Re: how to grab a ledge? - 08/14/08 14:40

hir`s a script of a player like zelda birki. thers just one problem he can`t die and can`t kill :

--------------------------------------------------------------------------------



string health_str = "HEALTH: ";

///////////////////////////////////////////////////////////////////////////////////

FUNCTION main() {
fps_max = 90; //set max fps
shadow_offset = 0.5; //distance entity shadow from surface
video_switch(8,32,1); //set screen resolution
camera.clip_near = 0; //stop camera clipping to world at close range
level_load("town.wmb"); //load level
}

DEFINE animdist,skill20;

var dist_planar = 200;
var dist_total = 200;
var dist_traced = 0;
var cam_xyangle = player_pan;
var cam_zangle = -15;
var zoffset = 7;
var panoffset = 0;
var viewvec[3];
var slowdown;
var cter = 0;
var player_diff[3];
var player_moveto[3];
var centerstop = 0;
var cam_radius = 400;
var cam_height = 70;
var cam_rotate_speed = 10; //rotation speed of camera when moving
var enable_mouse_move = 0;

var player_head_height = 42; //the distance from the origin to the head of the player
var player_feet_height = 32; //the distance from the origin to the feet of the player
var locked_on = 0;
var lockon_max = 400; //this is how far the player needs to be from the lock on, while locked on, in order to break the lock
var lockon_min = 300; //this is how close the player needs to be to a lock on target in order to iniate lock on when pressing right click
var locked_target[3];

var rotate_speed = 0;
var rotate_to = 0;
var are_we_strafing = 0;
var store_strafe_mode = 0;

var attack_state = 0;
var movement_mode = 0; //for various stages of moving
var ledge_climb_z; //this is set to 1 once the player is at a high enough point from climbing a ledge it is hanging onto, used to fix bug when player falls and grabs onto a thin ledge

var jump_z; //temporary variable, is copied into player_diff.z before the move instruction
var jump_force = 90; //change this variable to affect how high the player jumps
var jumping_mode = 0; //0 for not jumping, 1 if jumping
var z_force = 0;
var center[3];
var result = 0;

var global_cam_effect = 0; //the global radius change in rays hitting walls
var walk_speed = 5.5; //the number which running speed is divided by to get walking speed
var ledge_grab_test;

/////////////////////////////////////
entity* player;

/////////////////////////////////////////////

var camera_move_to = 200;
var cradius_speed = 20;

var planar_to = 200;
var camera_smooth_to[3];
var camera_pan_force = 0;
var camera_pan_velocity;

FUNCTION pan_back() {
IF (key_pgdn == 1) && (cam_height > -150) { cam_height -= 40 * time; }
IF (key_pgup == 1) && (cam_height < 300) { cam_height += 40 * time; }

IF (mouse_force.y < 0) && (cam_height > -150) { cam_height += 40 * mouse_force.y * time; }
IF (mouse_force.y > 0) && (cam_height < 300) { cam_height += 40 * mouse_force.y * time; }
IF (cam_height < -150) { cam_height = -150; }
IF (cam_height > 300) { cam_height = 300; }

player.z += 15; //temporarily changed so that camera focusus slightly above middle

temp.y = player.y - (dist_total - 10) * sin(cam_xyangle);
temp.x = player.x - (dist_total - 10) * cos(cam_xyangle);
temp.z = player.z + cam_height;
vec_diff(temp2.x,player.x,temp.x);
vec_normalize(temp2.x,16);
vec_add(temp.x,temp2.x);

trace_mode = ignore_me + ignore_passable;
trace (player.x, temp.x);
dist_traced = sqrt((target.x - player.x)*(target.x - player.x)+(target.y - player.y)*(target.y - player.y));

IF (dist_traced > 0) {
vec_set(temp.x,target.x);
vec_diff(temp2.x,player.x,target.x);
vec_normalize(temp2.x,16);
vec_add(temp.x,temp2.x);
result = sqrt((temp.x - my.x)*(temp.x - my.x) + (temp.y - my.y)*(temp.y - my.y));
IF (result < dist_total) { planar_to = result; }
} ELSE {
planar_to = dist_total;
}
camera_move_to.z = target.z;

player.z -= 15; //temporarily changed so that camera focusus slightly above middle

var temp2[3];
vec_set(temp2,camera.x);

vec_set(temp,my.x);
vec_sub(temp,temp2.x);
vec_to_angle(temp.pan,temp);
camera.tilt = temp.tilt + 7; //this causes the camera to tile towards the player

IF (abs(dist_planar - planar_to) > 2) {
cradius_speed = (dist_planar - planar_to) / -1;
} ELSE {
cradius_speed = 0;
my.skill15 = 0;
}

MY.skill15 += (TIME * cradius_speed) - (min(TIME*0.7,1) * my.skill15);
dist_planar += MY.skill15 * TIME;
dist_planar = planar_to;

trace_mode = ignore_me + ignore_passable;
result = trace (vector(camera.x,camera.y,player.z + 15),vector(camera.x,camera.y,camera.z + 5));
IF (result > 0) && (cam_height > result - 5) { cam_height = result - 5; }

cam_xyangle = cter;
camera_move_to.x = player.x - dist_planar * cos(cam_xyangle);
camera_move_to.y = player.y - dist_planar * sin(cam_xyangle);

//this is similar code to the template camera, the camera needs to be at the camera_move_to coordinates, this traces at a position, which smoothly moves towards the camera_move_to, and places the camera at the target.x vector, this works well because instead of placing the camera ta camera_move_to, it traces at a position which smoothly moves to camera_move_to
// move towards target position
temp2 = min(1,0.5 * time); // value of 1 places us at target, this value is what allows the smooth movement
camera_smooth_to.x += temp2*(camera_move_to.x - camera_smooth_to.x);
camera_smooth_to.y += temp2*(camera_move_to.y - camera_smooth_to.y);
camera_smooth_to.z += temp2*(camera_move_to.z - camera_smooth_to.z);

// keep camera from penetrating walls
vec_diff(temp2.x,camera_smooth_to.x,player.x);
vec_normalize(temp2.x,16);
vec_add(temp2.x,camera_smooth_to.x); // temp2 = temp_cdist + 16 units away from view target

me = player;
trace_mode = ignore_me + ignore_passable + ignore_models + ignore_sprites;
IF (trace(player.x,temp2.x) > 0) {
vec_diff(temp2.x,player.x,target.x);
vec_normalize(temp2.x,16);
vec_set(camera.x,target.x);
vec_add(camera.x,temp2.x);
} ELSE {
vec_set(camera.x,camera_smooth_to.x);
}
}


FUNCTION update_views(){
pan_back();
camera.pan = cam_xyangle;
camera.roll = 0;
}

////////////////////////////////////////////


FUNCTION init_cameras() {
beep;
camera.size_x = screen_size.x;
camera.size_y = screen_size.y;
camera.visible = on;
}


//////////////////////////////////////////////////

FUNCTION rotate_player(){
IF (jumping_mode == 0) { //so that player cannot control rotation in air
if(key_a == 1) {
rotate_to = cter + 90;
}
if(key_d == 1) {
rotate_to = cter + 270;
}
if(key_w == 1){
rotate_to = cter;
}
if(key_s == 1){
rotate_to = cter + 180;
}

if(key_w == 1 && key_d == 1){
rotate_to = cter + 315;
}

if(key_s == 1 && key_d){
rotate_to = cter + 225;
}

if(key_s == 1 && key_a == 1){
rotate_to = cter + 135;
}

if(key_w == 1 && key_a == 1){
rotate_to = cter + 45;
}

if((key_d == 1 && key_a == 1) || (key_w== 1 && key_s == 1)){
my.pan = my.pan;
rotate_to = my.pan;
}
}

IF (key_d == 1 || key_a == 1 || key_s == 1 || key_w == 1 || jumping_mode != 0) && (store_strafe_mode == 0) {
temp = ang(rotate_to - MY.PAN);
IF(temp > 5) {
rotate_speed = 20;
} ELSE {
IF (temp < -5) {
rotate_speed = -20;
} ELSE {
if(temp > -2) && (temp < 2) { my.skill14 = 0; }
rotate_speed = 3 * ang(rotate_to - MY.PAN);
}
}

MY.skill14 += (TIME * rotate_speed) - (min(TIME*0.7,1) * my.skill14);
MY.PAN += MY.skill14 * TIME;
}

if(cter > 359){ cter -= 360; }
}

//////////////////////////////////////////////////

FUNCTION movement(){
IF (key_a == 1) {
IF (key_shift == 0) {
cter += cam_rotate_speed * time;
} ELSE {
cter += cam_rotate_speed * time * 0.8;
}
player_moveto.x = (center.x + (cam_radius * cos(cter)));
player_moveto.y = (center.y + (cam_radius * sin(cter)));
player_moveto.z = player.z;
vec_diff(player_diff, player_moveto, player.x);
}
IF (key_d == 1) {
IF (key_shift == 0) {
cter -= cam_rotate_speed * time;
} ELSE {
cter -= cam_rotate_speed * time * 0.8;
}
player_moveto.x = (center.x + (cam_radius * cos(cter)));
player_moveto.y = (center.y + (cam_radius * sin(cter)));
vec_diff(player_diff, player_moveto, player.x);
player_moveto.z = player.z;
}

IF (cter > 359){ cter -= 360; }
IF (cter < 0){ cter += 360; }

IF (key_w == 1){
center.x += 10 * cos(cter);
center.y += 10 * sin(cter);
player_moveto.x = (center.x + cam_radius * cos(cter));
player_moveto.y = (center.y + cam_radius * sin(cter));
vec_diff(player_diff, player_moveto, player.x);
player_moveto.z = player.z;
}
IF (key_s == 1){
center.x -= 10 * cos(cter);
center.y -= 10 * sin(cter);
player_moveto.x = (center.x + cam_radius * cos(cter));
player_moveto.y = (center.y + cam_radius * sin(cter));
vec_diff(player_diff, player_moveto, player.x);
player_moveto.z = player.z;
}
IF(key_w == 0) && (key_s == 0) && (key_a == 0) && (key_d == 0) {
vec_set(player_diff, nullvector);
player_moveto.z = player.z;
}
}

FUNCTION strafe_movement(){

IF (key_a == 1) {
player_diff.y = 45 * time;
}
IF (key_d == 1) {
player_diff.y = -45 * time;
}
IF (key_w == 1) {
player_diff.x = 45 * time;
}
IF (key_s == 1) {
player_diff.x = -45 * time;
}
IF(key_w == 0) && (key_s == 0) && (key_a == 0) && (key_d == 0) {
vec_set(player_diff, nullvector);
}
}

//////////////

FUNCTION center_check(){
IF (player.x != (center.x + cam_radius * cos(cter))){
center.x = (player.x - cam_radius * cos(cter));
}
IF (player.y != (center.y + cam_radius * sin(cter))){
center.y = (player.y - cam_radius * sin(cter));
}
}

/////////////////////////////////////////////////////

var ladder_x[3];

ACTION player_action{
player = me;
vec_set(temp,player.x);
// create(<dummy.mdl>,temp,range200_action);
my.fat = off;
my.narrow = on;
my.animdist = 0;

//my.enable_detect = on;
//my.event = scan_event;

vec_set(temp,my.x);
temp.z -= 4000; // calculate a position 4000 quants below the player
trace_mode = ignore_me+ignore_sprites+ignore_passable+ignore_models+use_box;
result = trace(my.x,temp);// subtract vertical distance to ground
my.z -= result;

ledge_grab_test = 0;

locked_on = 0;
my.skill24 = 0;
are_we_strafing = 0;

WHILE (1){

IF (movement_mode == 0) {
IF (z_force < -2) { //are we falling?
vec_set(temp,my.x); //scan in front of player to see if he has hit a wall
temp.x += 30 * cos(my.pan);
temp.y += 30 * sin(my.pan);
temp.z = my.z + player_head_height; //scan at head height
trace_mode = ignore_me+ignore_sprites+ignore_models;
result = trace(my.x,temp);
IF(result == 0) {
ledge_grab_test = 0;
} ELSE {
IF (result > 0) && (ledge_grab_test == 0) {
vec_to_angle(temp,normal.x);
IF (abs(ang(my.pan - (temp.pan - 180))) < 30) {
temp2.pan = (temp.pan - 180); //make player face towards ladder
vec_set(temp,target.x); //scan to see if there is space up above player for it to grab onto ledge
temp.x += 10 * cos(temp2.pan);
temp.y += 10 * sin(temp2.pan);
temp.z += player_head_height - 2; //scan at head height
target.z += 10;
trace_mode = ignore_me+ignore_sprites+ignore_models;
result = trace(temp.x,target.x);
// vec_to_angle(temp,target.x);
IF (result > 0) { //if we have a wall in the way, and the surface above is less than a 10 degree slant
vec_set(temp,my.x); //scan to see if there is space up above player for it to grab onto ledge
temp.z += player_head_height - 2; //scan at head height
trace_mode = ignore_me+ignore_sprites+ignore_models;
result = trace(temp.x,target.x);
IF (result == 0) { //scan above head to make sure we didn't hit a roof
ledge_grab_test = 1;
movement_mode = 10;
my.pan = temp2.pan; //make player face towards ladder
}
}
}
}
}
}
}


IF (movement_mode == 1) { //ladder climbing
IF(key_w == 1) && (key_s == 0) {
temp.x = 0;
temp.y = 0;
temp.z = 5 * time;
ent_move(temp.x,nullvector);
vec_set(temp,my.x); //scan in front of player to see if there is a climbable wall
temp.x += 30 * cos(my.pan);
temp.y += 30 * sin(my.pan);
temp.z = my.z - 10;
trace_mode = ignore_me+ignore_sprites+ignore_models;
IF(trace(my.x,temp) == 0) {
movement_mode = 2;
}
ent_cycle("climb",my.animdist);
my.animdist += 2 * time;
}
IF(key_s == 1) && (key_w == 0) {
temp.x = 0;
temp.y = 0;
temp.z = -5 * time;
ent_move(temp.x,nullvector);
vec_set(temp,my.x);
temp.z -= 4000;
trace_mode = ignore_me+ignore_sprites+ignore_models+use_box;
result = trace(my.x,temp);
IF (result < 10) && (key_s == 1) { movement_mode = 0; }
ent_cycle("climb",my.animdist);
my.animdist += 2 * time;
}
IF (my.animdist > 100) { my.animdist -= 100; }
IF (ang(cter) < ang(player.pan)) {
IF (ang(player.pan) - ang(cter) <= 180) {
IF (ang(player.pan) - ang(cter) <= 5) {
cter += 0.25 * (ang(player.pan) - ang(cter));
} ELSE {
cter += cam_rotate_speed * 2 * time;
}
} ELSE {
cter -= cam_rotate_speed * 2 * time;
}
}
IF (ang(cter) > ang(player.pan)) {
IF (ang(cter) - ang(player.pan) <= 180) {
IF (ang(cter) - ang(player.pan) <= 5) {
cter += 0.25 * (ang(player.pan) - ang(cter));
} ELSE {
cter -= cam_rotate_speed * 2 * time;
}
} ELSE {
cter += cam_rotate_speed * 2 * time;
}
}
IF (cter > 359) { cter -= 360; }
IF (cter < 0) { cter += 360; }
// camera.z = player.z - sin(cam_zangle) * cam_height;
center_check();
update_views();
}

IF (movement_mode == 2) { //pulling yourself up onto a ledge
my.z += 5 * time;
player_diff.x = 1;
player_diff.y = 0;
player_diff.z = 0;
ent_move(player_diff.x,nullvector);
vec_set(temp,my.x); //scan in front of player to see if there is a climbable wall
temp.x += 30 * cos(my.pan);
temp.y += 30 * sin(my.pan);
temp.z = my.z - player_feet_height; //set the value 32 to the distance to the models feet
trace_mode = ignore_me+ignore_sprites+ignore_models;
IF(trace(my.x,temp) == 0) {
movement_mode = 3;
vec_set(ladder_x.x,my.x);
}
// camera.z = player.z - sin(cam_zangle) * cam_height;
ent_cycle("ladder",my.animdist);
my.animdist += 4 * time;
IF (my.animdist > 100) { my.animdist -= 100; }
center_check();
update_views();
}

IF (movement_mode == 3) { //moving a little bit forward so that player doesn't fall down
player_diff.x = 5 * time;
player_diff.y = 0;
vec_set(temp,my.x);
temp.z -= 4000; // calculate a position 4000 quants below the player
// set a trace mode for using the player's hull, and detecting map entities and level surfaces only
trace_mode = ignore_me+ignore_sprites+ignore_models+use_box;
result = trace(my.x,temp);// subtract vertical distance to ground
player_diff.z = 0;
IF (result < 4) { player_diff.z = -0.2 * result; }

IF(vec_dist(my.x,ladder_x.x) > 7) {
vec_set(temp,my.x);
temp.z -= 4000; // calculate a position 4000 quants below the player
// set a trace mode for using the player's hull, and detecting map entities and level surfaces only
trace_mode = ignore_me+ignore_sprites+ignore_models+use_box;
result = trace(my.x,temp);// subtract vertical distance to ground
IF (result < 4) { player_diff.z = -1 * result; }
} ELSE {
player_diff.z = 0;
}
ent_move(player_diff, nullvector);

IF(vec_dist(my.x,ladder_x.x) > 15) {
movement_mode = 0;
player_diff.z = 0;
z_force = 0;
jumping_mode = 0;
my.skill13 = 0;
}
ent_cycle("ladder",my.animdist);
my.animdist += 4 * time;
IF (my.animdist > 100) { my.animdist -= 100; }
center_check();
update_views();
}

IF (movement_mode == 10) {
IF (ang(cter) < ang(player.pan)) {
IF (ang(player.pan) - ang(cter) <= 180) {
IF (ang(player.pan) - ang(cter) <= 5) {
cter += 0.25 * (ang(player.pan) - ang(cter));
} ELSE {
cter += cam_rotate_speed * 1 * time;
}
} ELSE {
cter -= cam_rotate_speed * 1 * time;
}
}
IF (ang(cter) > ang(player.pan)) {
IF (ang(cter) - ang(player.pan) <= 180) {
IF (ang(cter) - ang(player.pan) <= 5) {
cter += 0.25 * (ang(player.pan) - ang(cter));
} ELSE {
cter -= cam_rotate_speed * 1 * time;
}
} ELSE {
cter += cam_rotate_speed * 1 * time;
}
}
IF (cter > 359) { cter -= 360; }
IF (cter < 0) { cter += 360; }


jumping_mode = 0;
player_diff.x = 0;
player_diff.z = 0;
z_force = 0;
IF (key_a != 0) && (key_d == 0) && (key_s == 0) && (key_w == 0) {
player_diff.y = 5 * time;
ent_cycle("ladder",my.animdist);
my.animdist += 4 * time;
} ELSE {
player_diff.y = 0;
}
IF (key_d != 0) && (key_a == 0) && (key_s == 0) && (key_w == 0) {
player_diff.y = -5 * time;
ent_cycle("ladder",my.animdist);
my.animdist += 4 * time;
} ELSE {
IF (key_a == 0) {
player_diff.y = 0;
}
}
IF (key_w == 1) && (key_s == 0) && (key_a == 0) && (key_d == 0) {
movement_mode = 11;
ledge_climb_z = my.z + player_head_height - 2; //this needs to be set to the height of the players head, ie my.z + # = players head
}
IF (key_s == 1) && (key_w == 0) && (key_a == 0) && (key_d == 0) {
movement_mode = 0;
jumping_mode = 0;
}
ent_move(player_diff, nullvector);
vec_set(temp,my.x); //scan in front of player to see if there is a climbable wall
temp.x += 30 * cos(my.pan);
temp.y += 30 * sin(my.pan);
temp.z = my.z + 40; //scan at head height
trace_mode = ignore_me+ignore_sprites+ignore_models;
result = trace(my.x,temp);
IF(result == 0) {
ledge_grab_test = 0;
movement_mode = 0;
jumping_mode = 0;
}

vec_set(temp,my.x); //scan a little above head height, we don't want a wall to be this high
temp.x += 30 * cos(my.pan);
temp.y += 30 * sin(my.pan);
temp.z += 45;
vec_set(temp2,my.x);
temp.z += 45;
trace_mode = ignore_me+ignore_sprites+ignore_models;
result = trace(temp2,temp);
IF(result > 0) {
ledge_grab_test = 0;
movement_mode = 0;
jumping_mode = 0;
}

center_check();
update_views();
IF (my.animdist > 100) { my.animdist -= 100; }
}


IF (movement_mode == 11) { //pulling yourself up onto a ledge
IF (my.z < ledge_climb_z) {
my.z += 5 * time;
} ELSE {
movement_mode = 12;
}
ent_cycle("ladder",my.animdist);
my.animdist += 4 * time;
IF (my.animdist > 100) { my.animdist -= 100; }
center_check();
update_views();
}

IF (movement_mode == 12) { //pulling yourself up onto a ledge
my.z += 5 * time;
player_diff.x = 1;
player_diff.y = 0;
player_diff.z = 0;
ent_move(player_diff.x,nullvector);
vec_set(temp,my.x); //scan in front of player to see if there is a climbable wall
temp.x += 30 * cos(my.pan);
temp.y += 30 * sin(my.pan);
temp.z = my.z - player_feet_height; //set the value player_feet_height to the distance to the models feet
trace_mode = ignore_me+ignore_sprites+ignore_models;
IF(trace(my.x,temp) == 0) {
movement_mode = 3;
vec_set(ladder_x.x,my.x);
}
// camera.z = player.z - sin(cam_zangle) * cam_height;
ent_cycle("ladder",my.animdist);
my.animdist += 4 * time;
IF (my.animdist > 100) { my.animdist -= 100; }
center_check();
update_views();
}



IF (movement_mode == 0) {
vec_set(temp,my.x); //scan in front of player to see if there is a climbable wall
temp.x += 30 * cos(my.pan);
temp.y += 30 * sin(my.pan);
temp.z = my.z;
trace_mode = ignore_me+ignore_sprites+ignore_models+scan_texture;
result = trace(my.x,temp);
// IF(str_cmpi(tex_name,"glas1") == 1) && (movement_mode == 0) { //change the texture here of the texture required to be tracing in order to climb wall
IF (tex_flag1 == on) && (movement_mode == 0) {
vec_to_angle(temp,normal.x);
IF (abs(ang(my.pan - (temp.pan - 180))) < 20) { movement_mode = 1; jumping_mode = 0; }
// my.pan = normal.pan - 180; //make player face towards ladder
}

vec_set(temp,my.x);
temp.z -= 4000; // calculate a position 4000 quants below the player
// set a trace mode for using the player's hull, and detecting map entities and level surfaces only
trace_mode = ignore_me+ignore_sprites+ignore_models+use_box;
result = trace(my.x,temp);// subtract vertical distance to ground
IF (key_space == 1) {
IF (jumping_mode == 0) { //if we are not already jumping
jumping_mode = 1;
z_force = jump_force;
my.animdist = 0;
IF (mouse_right == 1) || (key_x == 1) { store_strafe_mode = 1; } ELSE { store_strafe_mode = 0; }
}
}


IF (result <= 3) && (jumping_mode == 0) { // in the air?
IF (result < 1.3) && (result > -1.3) && (result > 0.5) && (result < -0.5) { my.skill13 = 0; } //change the value 1.5 to change how high steps he can climb, make it no higher than 3
vec_set(temp,my.x);
temp.z -= 4000; // calculate a position 4000 quants below the player
trace_mode = ignore_me+ignore_sprites+ignore_passable+ignore_models+use_box;
result = trace(my.x,temp);// subtract vertical distance to ground
z_force = -1 * result;
IF (mouse_right == 1) || (key_x == 1) { store_strafe_mode = 1; } ELSE { store_strafe_mode = 0; }
} ELSE {
IF (result <= 3) && (my.animdist > 20) {
IF (jumping_mode == 2) {
player_diff.x = 0;
player_diff.y = 0;
IF (my.animdist <= 40) { jumping_mode = 0; }
IF (my.animdist < 100) {
// ent_frame("jump",my.animdist);
// my.animdist += 7 * time;
} ELSE {
jumping_mode = 0;
}
}
IF (jumping_mode == 1) { my.skill13 = 0; jumping_mode = 0; }
IF (result < 1.3) && (result > -1.3) && (result > 0.5) && (result < -0.5) { my.skill13 = 0; } //change the value 1.5 to change how high steps he can climb, make it no higher than 3
vec_set(temp,my.x);
temp.z -= 4000; // calculate a position 4000 quants below the player
trace_mode = ignore_me+ignore_sprites+ignore_passable+ignore_models+use_box;
result = trace(my.x,temp);// subtract vertical distance to ground
z_force = -1 * result;
IF (mouse_right == 1) || (key_x == 1) { store_strafe_mode = 1; } ELSE { store_strafe_mode = 0; }
}
IF (jumping_mode == 1) {
IF (result > 30) { jumping_mode = 2; }
IF (my.animdist < 40) {
ent_frame("jump",my.animdist);
my.animdist += 5 * time;
} ELSE {
my.animdist = 40;
ent_frame("jump",my.animdist);
jumping_mode = 2;
}
IF (z_force > -20) { z_force -= 3 * time; } ELSE { z_force = -20; }
IF (jumping_mode == 0) {
IF (z_force > -20) { z_force -= 3 * time; } ELSE { z_force = -20; }
}
} ELSE {
IF (result < 30) {
IF (my.animdist < 80) {
ent_frame("jump",my.animdist);
my.animdist += 12 * time;
} ELSE {
ent_frame("jump",my.animdist);
my.animdist += 4 * time;
}
} ELSE {
IF (my.animdist < 40) {
ent_frame("hang",my.animdist);
my.animdist += 5 * time;
} ELSE {
my.animdist = 40;
ent_frame("jump",my.animdist);
jumping_mode = 2;
}
}
IF (z_force > -20) { z_force -= 3 * time; } ELSE { z_force = -20; }
}
}

IF (jumping_mode == 0) {
IF (key_x == 0) && (mouse_right == 0) {
rotate_player();
movement();
} ELSE {
strafe_movement();
}
move_mode = ignore_passable + glide;
player_diff.x /= 3;
player_diff.y /= 3;
IF (key_w == 1) && (key_d == 1) {
player_diff.x /= 1.5;
player_diff.y /= 1.5;
}
IF (key_w == 1) && (key_a == 1) {
player_diff.x /= 1.5;
player_diff.y /= 1.5;
}
IF (key_s == 1) && (key_d == 1) {
player_diff.x /= 1.5;
player_diff.y /= 1.5;
}
IF (key_s == 1) && (key_a == 1) {
player_diff.x /= 1.5;
player_diff.y /= 1.5;
}

IF (key_shift == 1) {
player_diff.x /= walk_speed;
player_diff.y /= walk_speed;
}

IF (key_w == 1) || (key_s == 1) || (key_d == 1) || (key_a == 1) {
IF (key_shift == 0) {
ent_cycle("run",my.animdist);
my.animdist += 15 * time;
} ELSE {
ent_cycle("run",my.animdist);
my.animdist += 9 * time;
}
} ELSE {
ent_cycle("stand",my.animdist);
my.animdist += 3 * time;
}
IF (my.animdist > 100) { my.animdist -= 100; }
} ELSE {
IF (locked_on != 1) && (locked_on != 1.5) {
rotate_player();
}
} //so player rotates towards moving direction in air, if they are not locked on

my.SKILL13 = 0.5*z_force + max(1-0.5*0.7,0)*my.SKILL13; // calculate vertical speed, replace 0.3 with time to convert to the old equation
jump_z = TIME * my.SKILL13; // distance down
player_diff.z = jump_z;

IF (jumping_mode != 0) { //stops changing of movement modes while jumping
key_x = 0;
mouse_right = store_strafe_mode;
}

IF (key_x == 0) && (mouse_right == 0) {
ent_move(nullvector, player_diff);
} ELSE {
ent_move(player_diff, nullvector);
}
center_check();
update_views();

//the following code moves the camera directly behind the player when holding the x key

IF (jumping_mode != 0) && (locked_on == 1.5) { //allow player to rotate around target while jumping
vec_set(temp.x,locked_target.x);
vec_sub(temp.x,my.x);
vec_to_angle(rotate_to,temp.x); // now MY looks at locked_target
IF (ang(rotate_to - my.pan) < -2) {
my.pan -= 12 * time;
}
IF (ang(rotate_to - my.pan) > 2) {
my.pan += 12 * time;
}
IF (abs(ang(rotate_to - my.pan)) > 5) { locked_on = 1; }
cter = my.pan;
}
IF (jumping_mode != 0) && (locked_on == 1) { //allow player to rotate around target while jumping
vec_set(temp.x,locked_target.x);
vec_sub(temp.x,my.x);
vec_to_angle(my.pan,temp.x); // now MY looks at locked_target
my.tilt = 0;
my.roll = 0;
cter = my.pan;
IF (vec_dist(my.x,locked_target.x) > lockon_max) { locked_on = 0; my.skill24 = 0; } //release lock if distance is greater than 320 & jumping
}

IF (jumping_mode == 0) {
IF (vec_dist(my.x,locked_target.x) > lockon_max) && (locked_on > 0) && (locked_on < 2) { locked_on = 0; my.skill24 = 0; } //release lock if distance is greater than 320 & walking
IF (key_x == 1 || mouse_right == 1) && (are_we_strafing != 2) {
are_we_strafing = 1;
IF (locked_on == 0) {
temp.pan = 360;
temp.tilt = 50;
temp.z = lockon_min;
scan_entity (my.x, temp);
locked_on = 2;
IF (my.skill24 == 1) { //if we scanned a lock on target
locked_on = 1.5;
} ELSE {
locked_on = 2;
}
}
IF (locked_on == 1.5) { //program smooth turning here
vec_set(temp.x,locked_target.x);
vec_sub(temp.x,my.x);
vec_to_angle(rotate_to,temp.x); // now MY looks at locked_target
IF (ang(rotate_to - my.pan) < -2) {
my.pan -= 12 * time;
}
IF (ang(rotate_to - my.pan) > 2) {
my.pan += 12 * time;
}
IF (abs(ang(rotate_to - my.pan)) < 5) { locked_on = 1; }
// cter = my.pan;
IF (ang(cter) < ang(player.pan)) {
IF (ang(player.pan) - ang(cter) <= 180) {
IF (ang(player.pan) - ang(cter) <= 5) {
cter += 0.25 * (ang(player.pan) - ang(cter));
cter = player.pan;
} ELSE {
cter += cam_rotate_speed * 5 * time;
}
} ELSE {
cter -= cam_rotate_speed * 5 * time;
}
}
IF (ang(cter) > ang(player.pan)) {
IF (ang(cter) - ang(player.pan) <= 180) {
IF (ang(cter) - ang(player.pan) <= 5) {
cter += 0.25 * (ang(player.pan) - ang(cter));
cter = player.pan;
} ELSE {
cter -= cam_rotate_speed * 5 * time;
}
} ELSE {
cter += cam_rotate_speed * 5 * time;
}
}
IF (cter > 359) { cter -= 360; }
IF (cter < 0) { cter += 360; }
}

IF (locked_on == 1) { //program smooth turning here
vec_set(temp.x,locked_target.x);
vec_sub(temp.x,my.x);
vec_to_angle(my.pan,temp.x); // now MY looks at locked_target
my.tilt = 0;
my.roll = 0;
cter = my.pan;
}
IF (locked_on == 2) {
IF (mouse_force.x > 0) { my.pan -= 10 * mouse_force.x * time; }
IF (mouse_force.x < 0) { my.pan -= 10 * mouse_force.x * time; }
IF (mouse_force.x == 0) {
IF (key_cul == 1 || key_cur == 1) { my.pan -= 10 * (key_cur - key_cul) * time; }
}
IF (abs(ang(cter - my.pan)) > 2) {
camera_pan_force = ang(cter - my.pan) / -3;
} ELSE {
camera_pan_force = 0;
camera_pan_velocity = 0;
}
camera_pan_velocity = 0.5*camera_pan_force + max(1-0.5*0.7,0) * camera_pan_velocity;
cter += camera_pan_velocity * TIME;
IF (cter > 359) { cter -= 360; }
IF (cter < 0) { cter += 360; }
}
}

IF (are_we_strafing == 1) && (mouse_right == 0) && (key_x == 0) { are_we_strafing = 2; locked_on = 0; my.skill24 = 0; } //2; }
IF (are_we_strafing == 2) {
IF (panoffset < 0) { panoffset += 3 * time; }
IF (panoffset > 0) { panoffset -= 3 * time; }
IF (zoffset < 6) { zoffset += 2 * time; }
IF (zoffset > 8) { zoffset -= 2 * time; }
IF (panoffset < 1 && panoffset > -1 && zoffset < 8 && zoffset > 6) { panoffset = 0; zoffset = 7; are_we_strafing = 0; }
}
}

//allows movement of camera with mouse when player is stationary
IF (mouse_force.x != 0) && (player_diff.x == 0) && (player_diff.z == 0) && (jumping_mode == 0) && (are_we_strafing == 0) {
IF (mouse_force.x > 0) { cter -= 10 * mouse_force.x * time; }
IF (mouse_force.x < 0) { cter -= 10 * mouse_force.x * time; }

//IF (mouse_force.x > 0) && (panoffset < 23) { panoffset += abs(mouse_force.x * 10 * time); }
//IF (mouse_force.x < 0) && (panoffset > -23) { panoffset -= abs(mouse_force.x * 10 * time); }
//IF (panoffset > 23) { panoffset = 23; }
//IF (panoffset < -23) { panoffset = -23; }
}
IF (mouse_force.y != 0) {
//IF (mouse_force.y > 0) && (zoffset > -8) { zoffset -= mouse_force.y * 10 * time; }
//IF (mouse_force.y < 0) && (zoffset < 17) { zoffset -= mouse_force.y * 10 * time; }
//IF (zoffset < -8) { zoffset = -8; }
//IF (zoffset > 17) { zoffset = 17; }
}
IF (mouse_left == 1) || (key_ctrl == 1) { //you can set various keys here to for various combos, then set different movement_modes for the different animations and actions
vec_set(temp,my.x);
temp.z -= 400;
trace_mode = ignore_me+ignore_sprites+ignore_passable+ignore_models+use_box;
result = trace(my.x,temp);
IF (result < 3) { //if we are on ground, not in the air
movement_mode = 100; //attacking
my.animdist = 100;
attack_state = 0;
}
}
}
IF (movement_mode == 100) {
basic_attack();
}
wait(1);
}
}

FUNCTION basic_attack() {
IF (my.animdist > 0) && (attack_state == 0) {
my.animdist -= 2 * time;
IF (my.animdist < 30) { //if we are far enough into attack animation
ent_vertex(temp,2698); //sword tip
ent_vertex(temp2,2698); //sword base
trace_mode = ignore_me + ignore_passable;
result = trace(temp2,temp);
IF (result != 0) {
IF (you != null) { //make sure we hit an entity and not a wall
your._health -= 5;
} ELSE { //if we hit a wall, rebound sword early
attack_state = 1;
}
}
}
IF (my.animdist <= 0) { my.animdist = 0; attack_state = 1; }
ent_frame("attack_a",my.animdist);
ground_player_elasticity();
}
IF (my.animdist < 100) && (attack_state == 1) {
my.animdist += 1 * time;
IF (my.animdist >= 100) { my.animdist = 100; attack_state = 0; movement_mode = 0; }
ent_frame("attack",my.animdist);
ground_player_elasticity();
}
}

FUNCTION ground_player_elasticity() {
vec_set(temp,my.x);
temp.z -= 4000; // calculate a position 4000 quants below the player
trace_mode = ignore_me+ignore_sprites+ignore_passable+ignore_models+use_box;
result = trace(my.x,temp);// subtract vertical distance to ground
z_force = -1 * result;
my.SKILL13 = 0.5*z_force + max(1-0.5*0.7,0)*my.SKILL13; // calculate vertical speed, replace 0.3 with time to convert to the old equation
jump_z = TIME * my.SKILL13; // distance down
player_diff.z = jump_z;
player_diff.x = 0;
player_diff.y = 0;

ent_move(player_diff, nullvector);
center_check();
update_views();
}

ACTION lock_on_object() {
my.skill25 = 1; //1 for lock on objects
my.shadow = on;
my.enable_scan = on;
my.skill26 = 0;
WHILE(1) {
IF (my.skill26 == 1) { //this allows the locked_target vector to change whilst the enemy is moving
vec_set(locked_target.x,my.x);
}
//put ai code here
wait(1);
}
}

FUNCTION scan_event {
IF (event_type == event_detect) {
you.skill26 = 0;
IF (you.skill25 == 1) {
IF (my.skill24 == 1) {
IF (vec_dist(my.x,you.x) <= vec_dist(my.x,locked_target.x)) { //if the next target is closer than previous
vec_set(locked_target.x,you.x);
you.skill26 = 1;
my.skill24 = 1;
}
}
IF (my.skill24 == 0) {
vec_set(locked_target.x,you.x);
you.skill26 = 1;
my.skill24 = 1;
}
}
}
}
© 2024 lite-C Forums