Below is updated Zelda code including:

- ladder climbing
- ledge grabbing
- very very basic combat
- FSW camera

---------------
Ladder climbing
---------------

If the player approaches a surface with flag 1 set to "on" the player will climb the wall like a ladder. The idea is to make a really thin tall block with

one of the surfaces flag 1 set to "on", then to make the block invisible and place a ladder model or sprite there. This doesn't work though as the trace

instruction which looks for a surface with flag 1 as "on" misses invisible blocks. The trace instruction wont detect invisible blocks.

---------------
Ledge grabbing
---------------

When falling, the player will grab onto a ledge, whilst on the ledge you can move left and right, drop down or climb up. The player will grab onto all

ledges even if they have a tilted surface. To stop the player grabbing onto tilted surfaces I suggest programming code to only grab onto walls with a

particular texture or flag set.

---------------
Combat
---------------

Place one or several entities into your level and give them the action lock_on_object. When you press and hold right click or x and are in range of one of

these entites you will lock on. Press ctrl or left click to do a basic attack. To get the attack working, merge a weapon in MED to the guard, get the

verticy numbers of the tip of the sword and the bottom of the sword. Change the values in the function basic_attack().

The combat code has not been improved from this because of my lack of animation skills (plus the amount of work it would take to get it working good).

--------------
Improved camera
--------------

The camera uses a basic FSW system. It doesn't stop clipping, but avoids it and makes the camera move better. The camera code can be tweaked to stop alot

of the clipping, but all the camera will do is stay soo close to the player that it has no chance of clipping.

--------------
Other
--------------

Holding shift will allow the player to walk, holding shift and jumping will cause the player to do a shorter jump.

Whilst holding right click or x use the mouse to pan the player (as long as you haven't locked on).

Copy the jump 2 animation of the guard and paste it into jump 3 (this will allow better looking jumps).

Press space to jump. I have changed the code to jump on space instead of approaching an edge, it seems a better way to play.

Please post any problems or suggestions.

Enjoy!



-------------------------------------------------------------------------------
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 = 270;
var cam_rotate_speed = 5; //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 temp2[6];
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 = 18; //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 = 1.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;

FUNCTION pan_back(){
/* dist_planar = dist_total; //old jump code

temp.x = player.x - dist_total * cos(cam_xyangle);
temp.y = player.y - dist_total * sin(cam_xyangle);
temp.z = player.z - sin(cam_zangle) * 200;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
dist_traced = vec_dist(target.x,player.x);
IF (dist_traced < dist_total) {
dist_traced -= 10; // Move it out of the wall
dist_planar = dist_traced;
} ELSE {
dist_planar = dist_total;
}
cam_xyangle = cter;
viewvec.x = player.x - dist_planar * cos(cam_xyangle);
viewvec.y = player.y - dist_planar * sin(cam_xyangle);
viewvec.z = player.z - sin(cam_zangle) * cam_height; */

temp.y = player.y - dist_total * sin(cam_xyangle);
temp.x = player.x - dist_total * cos(cam_xyangle);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
dist_traced = vec_dist(target.x,player.x);
IF (dist_traced < dist_total) {
dist_traced -= 15; // Move it out of the wall
camera_move_to = dist_traced;
} ELSE {
camera_move_to = dist_total;
}


temp.x = player.x - dist_total * cos(cam_xyangle + 5);
temp.y = player.y - dist_total * sin(cam_xyangle + 5);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
dist_traced = vec_dist(target.x,player.x);
IF (dist_traced < dist_total) {
camera_move_to -= (dist_total - dist_traced) / 1.3;
}


temp.x = player.x - dist_total * cos(cam_xyangle - 5);
temp.y = player.y - dist_total * sin(cam_xyangle - 5);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
result = vec_dist(target.x,player.x);
IF (result < dist_traced) {
dist_traced = result;
IF (dist_traced < dist_total) {
camera_move_to -= (dist_total - dist_traced) / 1.3;
}
}


temp.x = player.x - dist_total * cos(cam_xyangle + 10);
temp.y = player.y - dist_total * sin(cam_xyangle + 10);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
dist_traced = vec_dist(target.x,player.x);
IF (dist_traced < dist_total) {
camera_move_to -= (dist_total - dist_traced) / 3;
}


temp.x = player.x - dist_total * cos(cam_xyangle - 10);
temp.y = player.y - dist_total * sin(cam_xyangle - 10);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
result = vec_dist(target.x,player.x);
IF (result < dist_traced) {
dist_traced = result;
IF (dist_traced < dist_total) {
camera_move_to -= (dist_total - dist_traced) / 3;
}
}

temp.x = player.x - dist_total * cos(cam_xyangle + 22.5);
temp.y = player.y - dist_total * sin(cam_xyangle + 22.5);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
dist_traced = vec_dist(target.x,player.x);
IF (dist_traced < dist_total) {
camera_move_to -= (dist_total - dist_traced) / 5;
}


temp.x = player.x - dist_total * cos(cam_xyangle - 22.5);
temp.y = player.y - dist_total * sin(cam_xyangle - 22.5);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
result = vec_dist(target.x,player.x);
IF (result < dist_traced) {
dist_traced = result;
IF (dist_traced < dist_total) {
camera_move_to -= (dist_total - dist_traced) / 5;
}
}



temp.x = player.x - dist_total * cos(cam_xyangle + 35);
temp.y = player.y - dist_total * sin(cam_xyangle + 35);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
dist_traced = vec_dist(target.x,player.x);
IF (dist_traced < dist_total) {
camera_move_to -= (dist_total - dist_traced) / 10;
}

temp.x = player.x - dist_total * cos(cam_xyangle - 35);
temp.y = player.y - dist_total * sin(cam_xyangle - 35);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
result = vec_dist(target.x,player.x);
IF (result < dist_traced) {
dist_traced = result;
camera_move_to -= (dist_total - dist_traced) / 10;
}




temp.x = player.x - dist_total * cos(cam_xyangle + 50);
temp.y = player.y - dist_total * sin(cam_xyangle + 50);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
dist_traced = vec_dist(target.x,player.x);
IF (dist_traced < dist_total) {
camera_move_to -= (dist_total - dist_traced) / 15;
}

temp.x = player.x - dist_total * cos(cam_xyangle - 50);
temp.y = player.y - dist_total * sin(cam_xyangle - 50);
temp.z = camera.z;

trace_mode = ignore_me + ignore_passable + ignore_models;
trace (player.x, temp.x);
result = vec_dist(target.x,player.x);
IF (result < dist_traced) {
dist_traced = result;
camera_move_to -= (dist_total - dist_traced) / 15;
}

IF (camera_move_to < 15) { camera_move_to = 15; }
IF(abs(dist_planar - camera_move_to) < 20) {
cradius_speed = -0.25 * (dist_planar - camera_move_to);
} ELSE {
IF (dist_planar > camera_move_to) { cradius_speed = -25; }
IF (dist_planar < camera_move_to) { cradius_speed = 25; }
}
IF(abs(dist_planar - camera_move_to) < 50) { //deaccelerate camera before it reaches player
cradius_speed /= 1.3;
}
IF(abs(dist_planar - camera_move_to) < 40) { //deaccelerate camera before it reaches player
cradius_speed /= 1.3;
}
IF(abs(dist_planar - camera_move_to) < 30) {
cradius_speed /= 1.3;
}

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 + zoffset; //this causes the camera to tile towards the player


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

cam_xyangle = cter;
viewvec.x = player.x - dist_planar * cos(cam_xyangle);
viewvec.y = player.y - dist_planar * sin(cam_xyangle);
viewvec.z = player.z - sin(cam_zangle) * cam_height;


}


FUNCTION update_views(){
pan_back();
vec_set(camera.x, viewvec.x);
camera.pan = cam_xyangle - panoffset;
// camera.tilt = cam_zangle + zoffset;
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("walk",my.animdist);
my.animdist += 9 * 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("walk",my.animdist);
my.animdist += 9 * 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("walk",my.animdist);
my.animdist += 9 * 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 = 3 * 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("walk",my.animdist);
my.animdist += 9 * 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("walk",my.animdist);
my.animdist += 9 * 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("walk",my.animdist);
my.animdist += 9 * 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("walk",my.animdist);
my.animdist += 9 * 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("walk",my.animdist);
my.animdist += 9 * 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("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 (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 += 10 * time;
} ELSE {
ent_cycle("walk",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 -= 20 * mouse_force.x * time; cter = my.pan; }
IF (mouse_force.x < 0) { my.pan -= 20 * mouse_force.x * time; 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));
} 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));
} 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 (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) && (are_we_strafing == 0) {
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 -= 20 * time;
IF (my.animdist < 30) { //if we are far enough into attack animation
ent_vertex(temp,630); //sword tip
ent_vertex(temp2,601); //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
beep;
//put affecting variables in here, ie take damage off enemy, change enemy skill number so that enemy plays taking damage animation
} 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",my.animdist);
ground_player_elasticity();
}
IF (my.animdist < 100) && (attack_state == 1) {
my.animdist += 20 * 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;
}
}
}
}


Last edited by AccessPhenomenon; 12/25/04 09:09.