22466 lines
473 KiB
C++
22466 lines
473 KiB
C++
// Person.cpp
|
|
// Guy Simmons, 12th January 1998.
|
|
|
|
#include "Game.h"
|
|
#include "Cop.h"
|
|
#include "cam.h"
|
|
#include "Darci.h"
|
|
#include "Roper.h"
|
|
#include "Thug.h"
|
|
#include "id.h"
|
|
#include "statedef.h"
|
|
#include "animate.h"
|
|
#include "combat.h"
|
|
#include "sample.h"
|
|
#include "guns.h"
|
|
#include "cnet.h"
|
|
#include "interfac.h"
|
|
//#include "command.h"
|
|
#include "sewer.h"
|
|
#include "mav.h"
|
|
#include "Sound.h"
|
|
#include "eway.h"
|
|
#include "spark.h"
|
|
#include "drip.h"
|
|
#include "puddle.h"
|
|
#include "pap.h"
|
|
#include "supermap.h"
|
|
#include "ns.h"
|
|
#include "dirt.h"
|
|
#include "hook.h"
|
|
#include "pcom.h"
|
|
#include "tracks.h"
|
|
#include "C:\fallen\DDEngine\Headers\Matrix.h"
|
|
#include "ob.h"
|
|
#include "wmove.h"
|
|
#include "balloon.h"
|
|
#include "inside2.h"
|
|
#include "walkable.h"
|
|
#include "overlay.h"
|
|
#include "psystem.h"
|
|
#include "poly.h"
|
|
#include "memory.h"
|
|
#include "fmatrix.h"
|
|
#include "fc.h"
|
|
#include "mfx.h"
|
|
#include "night.h"
|
|
#include "ware.h"
|
|
#include "xlat_str.h"
|
|
#include "pow.h"
|
|
#include "frontend.h"
|
|
#ifdef PSX
|
|
#include "c:\fallen\psxeng\headers\psxeng.h"
|
|
#include "c:\fallen\psxeng\headers\panel.h"
|
|
#else
|
|
#include "aeng.h"
|
|
#include "panel.h"
|
|
#endif
|
|
|
|
#ifndef PSX
|
|
UBYTE player_visited[16][128];
|
|
extern SLONG save_psx;
|
|
#else
|
|
#define save_psx (1)
|
|
#endif
|
|
|
|
|
|
#ifdef TARGET_DC
|
|
#include "DIManager.h"
|
|
#endif
|
|
|
|
|
|
#define MAX_COL_WITH 16
|
|
|
|
|
|
extern Thing *is_person_under_attack_low_level(
|
|
Thing *p_person,
|
|
SLONG any_state,
|
|
SLONG radius);
|
|
|
|
|
|
/*
|
|
//MF_SOUND_API
|
|
|
|
|
|
//
|
|
// flags = MOVING/LOOPED/INTERRUPT/RESTART/???
|
|
//
|
|
|
|
//
|
|
// id is a general identification you give the sample so you can alter the playing sample later
|
|
// e.g a thing may use THING_NUMBER(p_thing) to generate a unique ID for the thing generating the sound effect
|
|
|
|
//
|
|
// the sound system will have to handle this stuff internally
|
|
//
|
|
|
|
MF_sfx_play_thing(UWORD id,Thing *p,UWORD sample,UWORD pitch,ULONG flags)
|
|
MF_sfx_play_pos(UWORD id,SLONG x,SLONG y,SLONg z,UWORD sample,UWORD pitch,ULONG flags)
|
|
MF_sfx_play_wpos(UWORD id,struct WorldPos *pos,UWORD sample,UWORD pitch,ULONG flags)
|
|
MF_sfx_play(UWORD id,UWORD sample,UWORD vol,UWORD pitch,ULONG flags);
|
|
|
|
//
|
|
// these functions alter samples allready playing, the sfx system will search for a playing sample with matching id and sample, to alter
|
|
//
|
|
MF_sfx_change_pitch_thing(UWORD id,UWORD sample)
|
|
MF_sfx_change_sample(UWORD id,UWORD old_sample,UWORD new_sample,ULONG flags)
|
|
MF_sfx_change_pos(UWORD id,UWORD sample,SLONG x,SLONG y,SLONG z)
|
|
|
|
MF_sfx_stop_sample(UWORD id,UWORD sample);
|
|
MF_sfx_stop_all();
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
//
|
|
// From Jan...
|
|
//
|
|
//
|
|
// There was a young actress from Crewe,
|
|
// Who remarked as the vicar withdrew,
|
|
// The Bishop was quicker
|
|
// and thicker and slicker,
|
|
// and two inches longer than you.
|
|
//
|
|
// There was a young vampire called mable,
|
|
// whose periods were always quite stable,
|
|
// at every full moon
|
|
// she took out a spoon,
|
|
// and drank herself under the table.
|
|
//
|
|
// There was a young plumber from Lee,
|
|
// who was plumbing his girl with great glee,
|
|
// she said stop your plumbing,
|
|
// I think someones coming,
|
|
// said the plumber still plumbing "its me"!
|
|
//
|
|
// A kinky young girl from Coleshill,
|
|
// Tried a dynamite stick for a thrill,
|
|
// They found her vagina,
|
|
// in North Carolina,
|
|
// and bits of her tits in Brazil.
|
|
//
|
|
// There was a young man from Pitlocherie,
|
|
// making love to his girl in the rockery,
|
|
// she said look you've cum,
|
|
// all over my bum,
|
|
// This isn't a shag it's a mockery.
|
|
//
|
|
// There was a young lassie from Morton,
|
|
// who had one long tit and one short 'en,
|
|
// on top of all that,
|
|
// a great hairy twat,
|
|
// and a fart like a six fifty Norton.
|
|
//
|
|
// There was a young man from Nantucket,
|
|
// Who's appendage was so long he could suck it,
|
|
// He was heard to allude,
|
|
// if I may be so crude,
|
|
// If my ear was a c*nt I could f*ck it.
|
|
//
|
|
|
|
|
|
// by mike
|
|
|
|
// There was a young stripper from London
|
|
// whos dress was easily undone
|
|
// with a quick flash
|
|
// we'd all see her Gash
|
|
// and shout out quite loudly, well done.
|
|
//
|
|
// ^^^^ this is rubbish, it doesn't fit the meter
|
|
|
|
// A girl named Jackie from Vancouver
|
|
// Liked to have sex with a hoover
|
|
// Until she met Chris
|
|
// While out on the piss
|
|
// Now she's a real sexy groover
|
|
|
|
#ifndef PSX
|
|
extern BOOL allow_debug_keys;
|
|
#endif
|
|
|
|
extern SLONG person_holding_2handed(Thing *p_person);
|
|
extern SLONG continue_dir(Thing *p_person,SLONG dir);
|
|
extern SLONG should_i_sneak(Thing *p_person);
|
|
extern void change_velocity_to(Thing *p_person,SWORD velocity);
|
|
extern void change_velocity_to_slow(Thing *p_person,SWORD velocity);
|
|
extern SLONG PAP_on_slope(SLONG x,SLONG z,SLONG *angle);
|
|
extern SLONG RFACE_on_slope(SLONG face,SLONG x,SLONG z,SLONG *angle);
|
|
extern void process_gang_attack(Thing *p_person,Thing *p_target);
|
|
extern void reset_gang_attack(Thing *p_target);
|
|
extern void drop_on_heads(Thing *p_thing);
|
|
extern UWORD count_gang(Thing *p_target);
|
|
extern void person_enter_fight_mode(Thing *p_person);
|
|
extern UWORD get_any_gang_member(Thing *p_target);
|
|
extern void add_damage_value_thing(Thing *p_thing,SLONG value);
|
|
extern void set_person_locked_idle_ready(Thing *p_person);
|
|
extern SLONG remove_from_gang_attack(Thing *p_person,Thing *p_target);
|
|
extern SLONG continue_pressing_action(Thing *p_person);
|
|
extern void set_action_used(Thing *p_person);
|
|
extern void carry_running(Thing *p_person);
|
|
extern void set_person_stand_carry(Thing *p_person);
|
|
|
|
|
|
extern UBYTE stealth_debug;
|
|
|
|
|
|
extern SLONG plant_feet(Thing *p_person);
|
|
extern SLONG calc_angle(SLONG dx,SLONG dz);
|
|
extern SLONG set_person_sidle(struct Thing *p_person);
|
|
extern SLONG slide_ladder;
|
|
|
|
extern SLONG yomp_speed;
|
|
extern SLONG sprint_speed;
|
|
|
|
UWORD player_dlight=0;
|
|
|
|
void aim_at_victim(Thing *p_person,SLONG count=1);
|
|
void set_anim_idle(Thing *p_person);
|
|
SLONG dist_to_target_pelvis(Thing *p_person_a,Thing *p_person_b);
|
|
UWORD find_arrestee(Thing *p_person);
|
|
void set_person_fight_idle(Thing *p_person);
|
|
SLONG set_person_pos_for_fence_vault(Thing *p_person,SLONG col);
|
|
|
|
SLONG check_near_facet(Thing *p_person,SLONG max_dist,SLONG max_end_dist,SLONG px,SLONG pz);
|
|
|
|
SLONG find_idle_fight_stance(Thing *p_person);
|
|
SLONG person_holding_special(Thing* p_person, UBYTE special);
|
|
SLONG person_holding_bat(Thing *p_person) { return person_holding_special(p_person, SPECIAL_BASEBALLBAT); }
|
|
void set_person_running(Thing *p_person);
|
|
|
|
void fn_person_moveing(Thing *p_person);
|
|
void fn_person_idle(Thing *p_person);
|
|
void fn_person_jumping(Thing *p_person);
|
|
void fn_person_dangling(Thing *p_person);
|
|
void fn_person_laddering(Thing *p_person);
|
|
void fn_person_climbing(Thing *p_person);
|
|
void fn_person_fighting(Thing *p_person);
|
|
void fn_person_recoil(Thing *p_person);
|
|
void fn_person_dying(Thing *p_person);
|
|
void fn_person_dead(Thing *p_person);
|
|
void fn_person_gun(Thing *p_person);
|
|
void fn_person_wait(Thing *p_person);
|
|
void fn_person_navigate(Thing *p_person);
|
|
void fn_person_fight(Thing *p_person);
|
|
void fn_person_stand_up(Thing *p_person);
|
|
void fn_person_mavigate(Thing *p_person);
|
|
void fn_person_grapple(Thing *p_person);
|
|
void fn_person_goto(Thing *p_person);
|
|
void fn_person_can(Thing *p_person);
|
|
void fn_person_circle(Thing *p_person);
|
|
void fn_person_hug_wall(Thing *p_person);
|
|
void fn_person_search(Thing *p_person);
|
|
void fn_person_carry(Thing *p_person);
|
|
void fn_person_float(Thing *p_person);
|
|
|
|
SLONG find_anim_fall_dir(SLONG anim);
|
|
|
|
SLONG set_person_pos_for_fence(Thing *p_person,SLONG col,SLONG set_pos,SLONG req_dist);
|
|
void locked_anim_change(Thing *p_person,UWORD locked_object,UWORD anim,SLONG dangle=0);
|
|
void do_person_on_cable(Thing *p_person);
|
|
SLONG fight_any_gang_attacker(Thing *p_person);
|
|
|
|
extern SLONG projectile_move_thing(Thing *p_thing,SLONG flag);
|
|
extern SLONG calc_height_at(SLONG x,SLONG z);
|
|
extern SLONG find_best_grapple(Thing *p_person);
|
|
|
|
SLONG set_person_pos_for_half_step(Thing *p_person,SLONG col);
|
|
void set_person_sneaking(Thing *p_person);
|
|
void set_person_mav_to_xz(Thing *p_person,SLONG x,SLONG z);
|
|
SLONG turn_to_face_thing(Thing *p_person,Thing *p_target,SLONG slow);
|
|
SLONG set_face_thing(Thing *p_person,Thing *p_target);
|
|
void set_person_mav_to_thing(Thing *p_person,Thing *p_target);
|
|
SLONG get_pitch_to_thing_quick(Thing *p_person,Thing *p_target);
|
|
void turn_to_face_thing_quick(Thing *p_person,Thing *p_target);
|
|
SLONG get_yomp_anim(Thing *p_person);
|
|
SLONG person_holding_2handed(Thing *p_person);
|
|
void drop_all_items(Thing *p_person, UBYTE is_being_searched);
|
|
void set_person_croutch(Thing *p_person);
|
|
void drop_current_gun(Thing *p_person,SLONG change_anim);
|
|
SLONG player_running_aim_gun(Thing *p_person);
|
|
SLONG might_i_be_a_villain(Thing *p_person);
|
|
void highlight_gun_target(Thing *p_person,Thing *p_target);
|
|
void locked_anim_change_of_type(Thing *p_person,UWORD locked_object,UWORD anim,SLONG type);
|
|
void set_anim_running(Thing *p_person);
|
|
|
|
extern void move_thing_on_map_dxdydz(Thing *t_thing,SLONG dx,SLONG dy,SLONG dz);
|
|
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
SLONG person_is_on_sewer(Thing *p_person);
|
|
#endif
|
|
|
|
|
|
GenusFunctions people_functions[] =
|
|
{
|
|
{ PERSON_DARCI, darci_states },
|
|
{ PERSON_ROPER, roper_states },//roper
|
|
{ PERSON_COP, cop_states },
|
|
{ PERSON_CIV, cop_states },
|
|
{ PERSON_THUG_RASTA, cop_states },
|
|
{ PERSON_THUG_GREY, cop_states },
|
|
{ PERSON_THUG_RED, cop_states },
|
|
{ PERSON_SLAG_TART, cop_states },
|
|
{ PERSON_SLAG_FATUGLY,cop_states },
|
|
{ PERSON_HOSTAGE, cop_states },
|
|
{ PERSON_MECHANIC, cop_states },
|
|
{ PERSON_TRAMP, cop_states },
|
|
{ PERSON_MIB1, cop_states },
|
|
{ PERSON_MIB2, cop_states },
|
|
{ PERSON_MIB3, cop_states },
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
StateFunction generic_people_functions[] =
|
|
{
|
|
{ STATE_INIT, NULL },
|
|
{ STATE_NORMAL, NULL },
|
|
{ STATE_HIT, NULL },
|
|
{ STATE_ABOUT_TO_REMOVE, NULL },
|
|
{ STATE_REMOVE_ME, NULL },
|
|
|
|
{ STATE_MOVEING, fn_person_moveing },
|
|
{ STATE_IDLE, fn_person_idle },
|
|
{ STATE_LANDING, NULL },
|
|
{ STATE_JUMPING, fn_person_jumping },
|
|
{ STATE_FIGHTING, fn_person_fighting },
|
|
{ STATE_FALLING, NULL },
|
|
{ STATE_USE_SCENERY, NULL },
|
|
{ STATE_DOWN, NULL },
|
|
{ STATE_HIT, NULL },
|
|
{ STATE_CHANGE_LOCATION, NULL },
|
|
{ STATE_DRIVING, NULL },
|
|
{ STATE_DYING, fn_person_dying },
|
|
{ STATE_DEAD, fn_person_dead },
|
|
{ STATE_DANGLING, fn_person_dangling },
|
|
{ STATE_CLIMB_LADDER, fn_person_laddering },
|
|
{ STATE_HIT_RECOIL, fn_person_recoil },
|
|
{ STATE_CLIMBING, fn_person_climbing },
|
|
{ STATE_GUN, fn_person_gun },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ STATE_NAVIGATING, fn_person_navigate },
|
|
{ STATE_WAIT, fn_person_wait },
|
|
{ STATE_FIGHT, fn_person_fight },
|
|
{ 0, NULL }, //stand up?
|
|
{ STATE_MAVIGATING, fn_person_mavigate },
|
|
{ STATE_GRAPPLING, fn_person_grapple },
|
|
{ STATE_GOTOING, fn_person_goto },
|
|
{ STATE_CANNING, fn_person_can },
|
|
{ STATE_CIRCLING, fn_person_circle },
|
|
{ STATE_HUG_WALL, fn_person_hug_wall },
|
|
{ STATE_SEARCH, fn_person_search },
|
|
{ STATE_CARRY, fn_person_carry },
|
|
{ STATE_FLOAT, fn_person_float },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
CBYTE *PERSON_mode_name[PERSON_MODE_NUMBER] =
|
|
{
|
|
"Run",
|
|
"Walk",
|
|
"Sneak",
|
|
"Fight"
|
|
};
|
|
|
|
SLONG stat_killed_thug;
|
|
SLONG stat_killed_innocent;
|
|
SLONG stat_arrested_thug;
|
|
SLONG stat_arrested_innocent;
|
|
SLONG stat_count_bonus;
|
|
SLONG stat_start_time,stat_game_time;
|
|
|
|
void set_stats(void)
|
|
{
|
|
stat_game_time=GetTickCount()-stat_start_time;
|
|
}
|
|
|
|
void init_stats(void)
|
|
{
|
|
stat_killed_thug=0;
|
|
stat_killed_innocent=0;
|
|
stat_arrested_thug=0;
|
|
stat_arrested_innocent=0;
|
|
stat_count_bonus=0;
|
|
stat_start_time=GetTickCount(); //I believe this is in PSX
|
|
}
|
|
|
|
|
|
/*
|
|
#define PERSON_NONE 100 // For debug...
|
|
#define PERSON_DARCI 0
|
|
#define PERSON_ROPER 1
|
|
#define PERSON_COP 2
|
|
#define PERSON_CIV 3
|
|
#define PERSON_THUG_RASTA 4
|
|
#define PERSON_THUG_GREY 5
|
|
#define PERSON_THUG_RED 6
|
|
#define PERSON_SLAG_TART 7
|
|
#define PERSON_SLAG_FATUGLY 8
|
|
#define PERSON_HOSTAGE 9
|
|
#define PERSON_MECHANIC 10
|
|
#define PERSON_NUMBER 11 // Number of people types.
|
|
*/
|
|
|
|
UBYTE anim_type[PERSON_NUM_TYPES] =
|
|
{
|
|
ANIM_TYPE_DARCI,
|
|
ANIM_TYPE_ROPER,
|
|
ANIM_TYPE_CIV,
|
|
ANIM_TYPE_CIV,
|
|
ANIM_TYPE_CIV,
|
|
ANIM_TYPE_CIV,
|
|
ANIM_TYPE_CIV,
|
|
ANIM_TYPE_DARCI,
|
|
ANIM_TYPE_DARCI,
|
|
ANIM_TYPE_DARCI,
|
|
ANIM_TYPE_CIV, //10
|
|
ANIM_TYPE_CIV, //11 tramp
|
|
ANIM_TYPE_CIV, //11 mib
|
|
ANIM_TYPE_CIV, //12
|
|
ANIM_TYPE_CIV //13
|
|
};
|
|
|
|
UBYTE mesh_type[PERSON_NUM_TYPES] =
|
|
{
|
|
0, //darci
|
|
0, //roper
|
|
4, //cop
|
|
7, //civ
|
|
0, //rasta
|
|
1, //thug grey
|
|
2, //thug red
|
|
1, //slag tart
|
|
2, //slag fatugly
|
|
3, //hostage
|
|
3, // ed miller , mechanic
|
|
6, //tramp
|
|
5, //mib
|
|
5,
|
|
5
|
|
};
|
|
|
|
SWORD health[PERSON_NUM_TYPES]=
|
|
{
|
|
200,
|
|
400,
|
|
200,
|
|
130,
|
|
200,
|
|
200,
|
|
200,
|
|
130,
|
|
130,
|
|
200,
|
|
200,
|
|
200,
|
|
700,
|
|
700,
|
|
700
|
|
};
|
|
|
|
|
|
|
|
#ifndef PSX
|
|
void set_player_visited(UBYTE x,UBYTE z)
|
|
{
|
|
UWORD bit;
|
|
ASSERT(WITHIN(x, 0, 127));
|
|
ASSERT(WITHIN(z, 0, 127));
|
|
bit=x&7;
|
|
x=x>>3;
|
|
player_visited[x][z]|=1<<bit;
|
|
|
|
}
|
|
#endif
|
|
|
|
inline BOOL MagicFrameCheck(Thing *p_person, UBYTE frameindex) {
|
|
if (p_person->Draw.Tweened->FrameIndex>=frameindex) {
|
|
if (!(p_person->Genus.Person->Flags2&FLAG2_SYNC_SOUNDFX)) {
|
|
p_person->Genus.Person->Flags2|=FLAG2_SYNC_SOUNDFX;
|
|
return TRUE;
|
|
}
|
|
} else {
|
|
p_person->Genus.Person->Flags2&=~FLAG2_SYNC_SOUNDFX;
|
|
}
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
BOOL PersonIsMIB(Thing* p_person)
|
|
{
|
|
return (p_person->Genus.Person->PersonType == PERSON_MIB1 ||
|
|
p_person->Genus.Person->PersonType == PERSON_MIB2 ||
|
|
p_person->Genus.Person->PersonType == PERSON_MIB3);
|
|
}
|
|
|
|
void SlideSoundCheck(Thing* p_person, BOOL force=0)
|
|
{
|
|
if (p_person->Genus.Person->Flags&FLAG_PERSON_SLIDING)
|
|
{
|
|
MFX_stop(THING_NUMBER(p_person),S_SEARCH_END);
|
|
if (force||!((p_person->State==STATE_MOVEING)&&(p_person->SubState==SUB_STATE_RUNNING_SKID_STOP)))
|
|
{
|
|
MFX_stop(THING_NUMBER(p_person),S_SLIDE_START);
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_SLIDING;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p_person->SubState==SUB_STATE_RUNNING_SKID_STOP)
|
|
{
|
|
#ifndef PSX
|
|
MFX_play_thing(THING_NUMBER(p_person),S_SLIDE_START,MFX_LOOPED,p_person);
|
|
#else
|
|
MFX_play_thing(THING_NUMBER(p_person),S_SLIDE_START,MFX_LOOPED|MFX_FLAG_SLIDER,p_person);
|
|
#endif
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_SLIDING;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
#ifndef PSX
|
|
void init_persons(void)
|
|
{
|
|
SLONG c0;
|
|
memset((UBYTE*)PEOPLE,0,sizeof(Person)*MAX_PEOPLE);
|
|
for(c0=0;c0<MAX_PEOPLE;c0++)
|
|
{
|
|
PEOPLE[c0].AnimType=PERSON_NONE;
|
|
}
|
|
PERSON_COUNT = 0;
|
|
}
|
|
#endif
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
Thing *alloc_person(UBYTE type, UBYTE random_number)
|
|
{
|
|
SLONG c0;
|
|
Person *new_person;
|
|
Thing *person_thing = NULL;
|
|
|
|
// if(type==1)
|
|
// type=4;
|
|
|
|
// Run through the people array & find an unused one.
|
|
for(c0=0;c0<MAX_PEOPLE;c0++)
|
|
{
|
|
if(PEOPLE[c0].AnimType==PERSON_NONE)
|
|
{
|
|
person_thing = alloc_thing(CLASS_PERSON);
|
|
if(person_thing)
|
|
{
|
|
new_person = TO_PERSON(c0);
|
|
new_person->PersonType = type;
|
|
|
|
new_person->AnimType = anim_type[type];
|
|
new_person->Thing = THING_NUMBER(person_thing);
|
|
new_person->PlayerID = 0;
|
|
new_person->Ammo = 15;
|
|
new_person->SpecialList = 0;
|
|
new_person->SpecialUse = 0;
|
|
new_person->Stamina = 128;
|
|
person_thing->Genus.Person = new_person;
|
|
person_thing->Draw.Tweened = alloc_draw_tween(DT_ROT_MULTI);
|
|
|
|
person_thing->OnFace = NULL;
|
|
|
|
person_thing->Draw.Tweened->TheChunk = &game_chunk[anim_type[type]];
|
|
/*
|
|
switch(anim_type[type])
|
|
{
|
|
case ANIM_TYPE_DARCI:
|
|
person_thing->Draw.Tweened->TheChunk = &game_chunk[anim_type[type]];
|
|
break;
|
|
case ANIM_TYPE_ROPER:
|
|
person_thing->Draw.Tweened->TheChunk = &game_chunk[2];
|
|
break;
|
|
case ANIM_TYPE_CIV:
|
|
person_thing->Draw.Tweened->TheChunk = &game_chunk[3];
|
|
break;
|
|
// case ANIM_TYPE_COP:
|
|
// person_thing->Draw.Tweened->TheChunk = &game_chunk[1];
|
|
break;
|
|
}
|
|
*/
|
|
|
|
person_thing->Draw.Tweened->MeshID = mesh_type[type];
|
|
#ifdef PSX
|
|
// ASSERT(person_thing->Draw.Tweened->MeshID||type==4);
|
|
#endif
|
|
/*
|
|
// aint true no more
|
|
if(save_psx)
|
|
{
|
|
//
|
|
// PSX don't have ugly whore
|
|
//
|
|
if(person_thing->Draw.Tweened->MeshID==6)
|
|
person_thing->Draw.Tweened->MeshID=5;
|
|
else
|
|
if(person_thing->Draw.Tweened->MeshID==8)
|
|
person_thing->Draw.Tweened->MeshID=6;
|
|
}
|
|
*/
|
|
|
|
|
|
/*
|
|
|
|
//if(new_person->AnimType==ANIM_TYPE_CIV && person_thing->Draw.Tweened->MeshID==0)
|
|
if(type==PERSON_THUG)
|
|
{
|
|
SLONG mesh=Random()%2;
|
|
|
|
person_thing->Draw.Tweened->MeshID = mesh+1; //normal thug
|
|
|
|
|
|
}
|
|
else
|
|
if(type==PERSON_THUG2)
|
|
{
|
|
SLONG mesh=Random()%5;
|
|
switch(mesh)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
person_thing->Draw.Tweened->MeshID = mesh; //normal thug
|
|
break;
|
|
case 3:
|
|
person_thing->Draw.Tweened->MeshID = 8; // mechanic
|
|
break;
|
|
case 4:
|
|
person_thing->Draw.Tweened->MeshID = 5; //slag1
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if(type==PERSON_CIV || type==PERSON_CIV2)
|
|
{
|
|
person_thing->Draw.Tweened->PersonID=6+Random()%6;
|
|
if(person_thing->Draw.Tweened->PersonID==10)
|
|
{
|
|
person_thing->Draw.Tweened->PersonID=0;
|
|
person_thing->Draw.Tweened->MeshID = 7; //hostage
|
|
}
|
|
if(person_thing->Draw.Tweened->PersonID==11)
|
|
{
|
|
person_thing->Draw.Tweened->PersonID=0;
|
|
person_thing->Draw.Tweened->MeshID = 6; //ugly slag (real ugly)
|
|
}
|
|
}
|
|
|
|
*/
|
|
|
|
if (type == PERSON_CIV)
|
|
{
|
|
//
|
|
// A civ's PersonID makes him look different.
|
|
//
|
|
|
|
person_thing->Draw.Tweened->PersonID = 6 + random_number % 4;
|
|
// if(Random()&1)
|
|
// person_thing->Draw.Tweened->MeshID ++; //make it a bloke
|
|
}
|
|
/*
|
|
if (type == PERSON_MIB2)
|
|
{
|
|
person_thing->Draw.Tweened->PersonID = 1;
|
|
}
|
|
if (type == PERSON_MIB3)
|
|
{
|
|
person_thing->Draw.Tweened->PersonID = 2;
|
|
}
|
|
*/
|
|
|
|
set_state_function(person_thing,STATE_INIT);
|
|
person_thing->Genus.Person->Health=health[type];
|
|
return(person_thing);
|
|
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
ASSERT(0);
|
|
return person_thing;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
void free_person(Thing *person_thing)
|
|
{
|
|
// Set the person type to none & free the thing.
|
|
person_thing->Genus.Person->AnimType = PERSON_NONE;
|
|
free_draw_tween(person_thing->Draw.Tweened);
|
|
person_thing->Draw.Tweened=0; // clear the pointer just incase
|
|
|
|
free_thing(person_thing);
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
UBYTE global_person=0;
|
|
|
|
THING_INDEX create_person(
|
|
SLONG type,
|
|
SLONG random_number,
|
|
SLONG x,
|
|
SLONG y,
|
|
SLONG z)
|
|
{
|
|
Thing *p_person = alloc_person(type, random_number);
|
|
global_person++;
|
|
|
|
|
|
|
|
if (p_person)
|
|
{
|
|
#ifndef PSX
|
|
#ifndef TARGET_DC
|
|
|
|
extern SWORD people_types[50];
|
|
people_types[type]++;
|
|
#endif
|
|
#endif
|
|
// ASSERT(THING_NUMBER(p_person)!=195);
|
|
p_person->WorldPos.X = x;
|
|
p_person->WorldPos.Y = y;
|
|
p_person->WorldPos.Z = z;
|
|
|
|
// ASSERT(!(MAV_SPARE(x>>16,z>>16) & MAV_SPARE_FLAG_WATER));
|
|
|
|
p_person->Genus.Person->HomeX = x >> 8;
|
|
p_person->Genus.Person->HomeZ = z >> 8;
|
|
|
|
|
|
//
|
|
// Is this person on a building?
|
|
//
|
|
|
|
SLONG new_y;
|
|
SLONG face = find_face_for_this_pos(
|
|
x >> 8,
|
|
y >> 8,
|
|
z >> 8,
|
|
&new_y,
|
|
NULL,0);
|
|
|
|
// ASSERT(type!=PERSON_DARCI);
|
|
|
|
if (face)
|
|
{
|
|
if (face == GRAB_FLOOR)
|
|
{
|
|
|
|
p_person->WorldPos.Y = new_y << 8;
|
|
//
|
|
// No problem.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Put the person on this face.
|
|
//
|
|
|
|
p_person->OnFace = face;
|
|
p_person->WorldPos.Y = new_y << 8;
|
|
}
|
|
}
|
|
|
|
// plant_feet(p_person); // ?
|
|
|
|
//
|
|
// Is this person inside a warehouse?
|
|
//
|
|
|
|
if (PAP_2HI(
|
|
p_person->WorldPos.X >> 16,
|
|
p_person->WorldPos.Z >> 16).Flags & PAP_FLAG_HIDDEN)
|
|
{
|
|
SLONG ware_top;
|
|
|
|
ware_top = PAP_calc_map_height_at(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
|
|
if (p_person->WorldPos.Y < (ware_top - 0x80 << 8))
|
|
{
|
|
p_person->Genus.Person->Ware = WARE_which_contains(
|
|
p_person->WorldPos.X >> 16,
|
|
p_person->WorldPos.Z >> 16);
|
|
|
|
if (p_person->Genus.Person->Ware)
|
|
{
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_WAREHOUSE;
|
|
p_person->Genus.Person->Flags2 |= FLAG2_PERSON_HOME_IN_WAREHOUSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initialise the person straight away!
|
|
//
|
|
|
|
PTIME(p_person)=(UBYTE)Random();
|
|
p_person->StateFn(p_person);
|
|
|
|
return THING_NUMBER(p_person);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Returns TRUE if there is enough room in front of the given person.
|
|
//
|
|
|
|
SLONG is_there_room_in_front_of_me(Thing *p_person, SLONG how_much_room)
|
|
{
|
|
SLONG x1;
|
|
SLONG y1;
|
|
SLONG z1;
|
|
|
|
SLONG x2;
|
|
SLONG y2;
|
|
SLONG z2;
|
|
|
|
SLONG dx;
|
|
SLONG dz;
|
|
|
|
x1 = p_person->WorldPos.X >> 8;
|
|
y1 = p_person->WorldPos.Y + 0x6000 >> 8;
|
|
z1 = p_person->WorldPos.Z >> 8;
|
|
|
|
dx = -SIN(p_person->Draw.Tweened->Angle) * how_much_room >> 16;
|
|
dz = -COS(p_person->Draw.Tweened->Angle) * how_much_room >> 16;
|
|
|
|
x2 = x1 + dx;
|
|
z2 = z1 + dz;
|
|
|
|
y2 = PAP_calc_map_height_at(x2,z2) + 0x60;
|
|
|
|
if (abs(y1 - y2) > 0x40)
|
|
{
|
|
//
|
|
// Too much height difference.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (!there_is_a_los(
|
|
x1, y1, z1,
|
|
x2, y2, z2,
|
|
LOS_FLAG_IGNORE_SEETHROUGH_FENCE_FLAG))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
extern THING_INDEX col_with[];
|
|
|
|
SLONG find_searchable_person(Thing *p_person)
|
|
{
|
|
SLONG col_with_upto;
|
|
SLONG collide_types = (1 << CLASS_PERSON);
|
|
Thing *col_thing;
|
|
SLONG i;
|
|
SLONG best_dist=INFINITY,best_index=0,dist;
|
|
|
|
col_with_upto = THING_find_sphere(
|
|
p_person->WorldPos.X>>8,
|
|
p_person->WorldPos.Y>>8,
|
|
p_person->WorldPos.Z>>8,
|
|
256,
|
|
col_with,
|
|
MAX_COL_WITH,
|
|
collide_types);
|
|
|
|
for (i = 0; i < col_with_upto; i++)
|
|
{
|
|
col_thing = TO_THING(col_with[i]);
|
|
|
|
if (col_thing->State == STATE_DEAD && (col_thing->SubState==SUB_STATE_DEAD_ARRESTED||col_thing->SubState==0) && !(col_thing->Genus.Person->Flags&FLAG_PERSON_SEARCHED))
|
|
{
|
|
dist=dist_to_target_pelvis(p_person,col_thing);
|
|
if(dist<best_dist)
|
|
{
|
|
best_dist=dist;
|
|
best_index=col_with[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
if(best_dist<64)
|
|
{
|
|
return(best_index);
|
|
|
|
}
|
|
else
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
SLONG set_person_search(Thing *p_person, SLONG ob_index,SLONG ox,SLONG oy,SLONG oz)
|
|
{
|
|
SLONG dx,dz,angle,dangle;
|
|
|
|
dx=(p_person->WorldPos.X>>8)-ox;
|
|
dz=(p_person->WorldPos.Z>>8)-oz;
|
|
|
|
angle=calc_angle(dx,dz);
|
|
dangle=angle-p_person->Draw.Tweened->Angle;
|
|
|
|
if(abs(dangle)<256 || angle>2048-256)
|
|
{
|
|
|
|
p_person->Draw.Tweened->Angle=angle;
|
|
set_person_locked_idle_ready(p_person);
|
|
set_generic_person_state_function(p_person,STATE_SEARCH);
|
|
p_person->SubState=SUB_STATE_SEARCH_PRIM;
|
|
p_person->Genus.Person->Timer1=0;
|
|
p_person->Genus.Person->Flags |= (FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
p_person->Genus.Person->Action=ACTION_NONE;
|
|
p_person->Genus.Person->Target=ob_index;
|
|
return(1);
|
|
}
|
|
else
|
|
return(0);
|
|
|
|
}
|
|
|
|
SLONG set_person_search_corpse(Thing *p_person, Thing *p_dead)
|
|
{
|
|
|
|
// set_person_locked_idle_ready(p_person);
|
|
|
|
set_anim(p_person, ANIM_CROUTCH_DOWN);
|
|
|
|
set_generic_person_state_function(p_person,STATE_SEARCH);
|
|
p_person->SubState=SUB_STATE_SEARCH_CORPSE;
|
|
p_person->Genus.Person->Timer1=0;
|
|
p_person->Genus.Person->Flags |= (FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
p_person->Genus.Person->Action=ACTION_NONE;
|
|
p_person->Genus.Person->Target=THING_NUMBER(p_dead);
|
|
#ifndef PSX
|
|
MFX_play_ambient(THING_NUMBER(p_person),S_SEARCH_END,MFX_LOOPED);
|
|
#else
|
|
MFX_play_ambient(THING_NUMBER(p_person),S_SEARCH_END,MFX_LOOPED|MFX_FLAG_SEARCHER);
|
|
#endif
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_SLIDING; // cunning lie.
|
|
return(1);
|
|
}
|
|
|
|
void release_searched_item(Thing *p_person)
|
|
{
|
|
SLONG index;
|
|
Thing *p_thing;
|
|
SLONG ob_index;
|
|
|
|
MFX_stop(THING_NUMBER(p_person),S_SEARCH_END);
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_SEARCH_CORPSE:
|
|
drop_all_items(TO_THING(p_person->Genus.Person->Target),1);
|
|
ASSERT(TO_THING(p_person->Genus.Person->Target)->Class==CLASS_PERSON);
|
|
TO_THING(p_person->Genus.Person->Target)->Genus.Person->Flags|=FLAG_PERSON_SEARCHED;
|
|
MFX_play_ambient(THING_NUMBER(p_person),S_HIDDENITEM,0);
|
|
break;
|
|
case SUB_STATE_SEARCH_PRIM:
|
|
ob_index=p_person->Genus.Person->Target;
|
|
p_person->Genus.Person->Target=0;
|
|
|
|
if(!(OB_ob[ob_index].flags&OB_FLAG_HIDDEN_ITEM))
|
|
{
|
|
return;
|
|
}
|
|
|
|
MFX_play_ambient(THING_NUMBER(p_person),S_HIDDENITEM,0);
|
|
index=thing_class_head[CLASS_SPECIAL];
|
|
while(index)
|
|
{
|
|
|
|
p_thing=TO_THING(index);
|
|
if(p_thing->Flags&FLAG_SPECIAL_HIDDEN)
|
|
{
|
|
if(p_thing->Genus.Special->counter==ob_index)
|
|
{
|
|
add_thing_to_map(p_thing);
|
|
p_thing->Flags&=~FLAG_SPECIAL_HIDDEN;
|
|
p_thing->Genus.Special->counter = 0;
|
|
OB_ob[ob_index].flags&=~OB_FLAG_HIDDEN_ITEM;
|
|
}
|
|
}
|
|
|
|
index=p_thing->NextLink;
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Returns a place on the ground near the given person.
|
|
//
|
|
|
|
void find_nice_place_near_person(
|
|
Thing *p_person,
|
|
SLONG *nice_x, // 8-bits per mapsquare
|
|
SLONG *nice_y,
|
|
SLONG *nice_z)
|
|
{
|
|
SLONG gx;
|
|
SLONG gy;
|
|
SLONG gz;
|
|
|
|
SLONG px,py,pz;
|
|
|
|
//
|
|
// Anywhere on the same mapsquare as the person should do!
|
|
//
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_PELVIS,
|
|
&px,
|
|
&py,
|
|
&pz);
|
|
|
|
px = px + (p_person->WorldPos.X >> 8);
|
|
py = py + (p_person->WorldPos.Y >> 8);
|
|
pz = pz + (p_person->WorldPos.Z >> 8);
|
|
|
|
gx = (((px) & 0xff00) | (Random() & 0x1f)) + 0x3f;
|
|
gz = (((pz) & 0xff00) | (Random() & 0x1f)) + 0x3f;
|
|
|
|
gy = PAP_calc_height_at_thing(p_person,gx,gz);
|
|
|
|
//
|
|
// If there is a huge difference in y, then it ain't a nice place!
|
|
//
|
|
|
|
if (abs(gy - (p_person->WorldPos.Y >> 8)) > 0x50)
|
|
{
|
|
gx = p_person->WorldPos.X >> 8;
|
|
gz = p_person->WorldPos.Z >> 8;
|
|
|
|
gy = PAP_calc_height_at_thing(p_person,gx,gz);
|
|
}
|
|
|
|
*nice_x = gx;
|
|
*nice_y = gy + 0x30; // above the ground a little bit..
|
|
*nice_z = gz;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Valid substates are
|
|
//
|
|
// SUB_STATE_DYING_INITIAL_ANI
|
|
// SUB_STATE_DYING_FINAL_ANI
|
|
// SUB_STATE_DYING_KNOCK_DOWN - means they play a get up animation after their current animation is over and don't die.
|
|
//
|
|
|
|
void set_person_dying(Thing *p_person, UBYTE substate)
|
|
{
|
|
//
|
|
// Valid substate?
|
|
//
|
|
|
|
ASSERT(
|
|
substate == SUB_STATE_DYING_ACTUALLY_DIE ||
|
|
substate == SUB_STATE_DYING_INITIAL_ANI ||
|
|
substate == SUB_STATE_DYING_FINAL_ANI ||
|
|
substate == SUB_STATE_DYING_KNOCK_DOWN ||
|
|
substate == SUB_STATE_DYING_KNOCK_DOWN_WAIT);
|
|
|
|
//
|
|
// Let go of any balloon you may have.
|
|
//
|
|
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
if (p_person->Genus.Person->Balloon)
|
|
{
|
|
BALLOON_release(p_person->Genus.Person->Balloon);
|
|
}
|
|
#endif
|
|
|
|
set_generic_person_state_function(p_person,STATE_DYING);
|
|
|
|
p_person->Velocity = 0;
|
|
p_person->Genus.Person->Action = ACTION_DYING;
|
|
p_person->SubState = substate;
|
|
p_person->Genus.Person->Flags |= (FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
//
|
|
// The pcom ai counter is used to count how long somebody is dead.
|
|
//
|
|
|
|
p_person->Genus.Person->pcom_ai_counter = 0;
|
|
|
|
if ((substate == SUB_STATE_DYING_KNOCK_DOWN)||(substate == SUB_STATE_DYING_KNOCK_DOWN_WAIT))
|
|
return; // only continue if they're actually _dying_.
|
|
|
|
if (PersonIsMIB(p_person))
|
|
{
|
|
// MFX_play_ambient(0,S_THUNDER_START+(Random()&1),0);
|
|
MFX_play_thing(THING_NUMBER(p_person),S_MIB_LEVITATE,MFX_LOOPED,p_person);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Returns if the person is lying on his front or back
|
|
//
|
|
|
|
#define PERSON_ON_HIS_FRONT 0
|
|
#define PERSON_ON_HIS_BACK 1
|
|
#define PERSON_ON_HIS_SOMETHING 2
|
|
|
|
SLONG person_is_lying_on_what(Thing *p_person)
|
|
{
|
|
ASSERT(p_person->Class == CLASS_PERSON);
|
|
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_KO_BEHIND_BIG:
|
|
case ANIM_KO_BEHIND_BIG_GU:
|
|
case ANIM_KD_FRONT_LOW:
|
|
case ANIM_KD_FRONT_MID:
|
|
case ANIM_KD_FRONT_HI:
|
|
case ANIM_FIGHT_STOMPED_BACK:
|
|
case ANIM_KD_FRONT_LAND:
|
|
case ANIM_HANDS_UP_LIE:
|
|
case ANIM_PISTOL_WHIP_TAKE:
|
|
return PERSON_ON_HIS_FRONT;
|
|
|
|
case ANIM_KO_BACK:
|
|
case ANIM_KO_BACK_GU:
|
|
case ANIM_KD_BACK_LOW:
|
|
case ANIM_KD_BACK_MID:
|
|
case ANIM_KD_BACK_HI:
|
|
case ANIM_FIGHT_STOMPED_FRONT:
|
|
case ANIM_KD_BACK_LAND:
|
|
case ANIM_GRAB_ARM_THROWV:
|
|
case ANIM_STRANGLE_VICTIM:
|
|
case ANIM_HEADBUTT_VICTIM:
|
|
return(PERSON_ON_HIS_BACK);
|
|
|
|
default:
|
|
#ifndef NDEBUG
|
|
return PERSON_ON_HIS_SOMETHING;
|
|
#else
|
|
return(PERSON_ON_HIS_BACK);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
SLONG footstep_wave(Thing *p_person)
|
|
{
|
|
//
|
|
// Which one out of a choice of sounds we play.
|
|
//
|
|
|
|
// static SLONG which;
|
|
|
|
SLONG start;
|
|
SLONG end;
|
|
SLONG num;
|
|
|
|
if (p_person->Genus.Person->Ware)
|
|
{
|
|
// in a warehouse. generic texture.
|
|
#ifndef PSX
|
|
return SOUND_Range(S_SOFT_STEP_START,S_SOFT_STEP_END);
|
|
#else
|
|
return S_FOOTS_ROAD_START;
|
|
#endif
|
|
}
|
|
|
|
switch(num=person_is_on(p_person))
|
|
{
|
|
|
|
case PERSON_ON_DUNNO:
|
|
case PERSON_ON_PRIM:
|
|
start = S_FOOTS_ROAD_START;
|
|
end = S_FOOTS_ROAD_END;
|
|
break;
|
|
#ifndef PSX
|
|
case PERSON_ON_WATER:
|
|
start = S_FOOTS_PUDDLE_START;
|
|
end = S_FOOTS_PUDDLE_END;
|
|
break;
|
|
|
|
case PERSON_ON_SEWATER:
|
|
start = S_FOOTS_SEWER_START;
|
|
end = S_FOOTS_SEWER_END;
|
|
break;
|
|
#endif
|
|
case PERSON_ON_METAL:
|
|
start = S_FOOTS_RUNG_START;
|
|
end = S_FOOTS_RUNG_END;
|
|
break;
|
|
/*
|
|
case PERSON_ON_PRIM:
|
|
start = S_FOOTS_CAR_START;
|
|
end = S_FOOTS_CAR_END;
|
|
break;
|
|
*/
|
|
#ifndef PSX
|
|
case PERSON_ON_GRAVEL:
|
|
// case PERSON_ON_PRIM:
|
|
start = S_FOOTS_GRAVEL_START;
|
|
end = S_FOOTS_GRAVEL_END;
|
|
break;
|
|
|
|
case PERSON_ON_WOOD:
|
|
start = S_FOOTS_WOOD_START;
|
|
end = S_FOOTS_WOOD_END;
|
|
break;
|
|
|
|
case PERSON_ON_GRASS:
|
|
start = S_FOOTS_GRASS_START;
|
|
end = S_FOOTS_GRASS_END;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
#ifndef PSX
|
|
if (num==0xff) num=0;
|
|
if (num<=0) { // we have a specific index. woo
|
|
start = SOUND_FXGroups[-num][0];
|
|
end = SOUND_FXGroups[-num][1];
|
|
//TRACE("footstep range %d to %d, num was %d\n",start,end,num);
|
|
} else {
|
|
ASSERT(0);
|
|
}
|
|
#else
|
|
start = S_FOOTS_ROAD_START;
|
|
end = S_FOOTS_ROAD_END;
|
|
#endif
|
|
break;
|
|
}
|
|
#ifndef PSX
|
|
return SOUND_Range(start,end);
|
|
#else
|
|
return start;
|
|
#endif
|
|
|
|
/* num = end - start + 1;
|
|
|
|
return (which++ % num) + start;*/
|
|
}
|
|
|
|
//
|
|
// Returns the relative angle of the target from the person.
|
|
//
|
|
|
|
SLONG get_dangle(Thing *p_person, Thing *p_target)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG angle;
|
|
SLONG dangle;
|
|
|
|
dx = p_target->WorldPos.X - p_person->WorldPos.X >> 8;
|
|
dz = p_target->WorldPos.Z - p_person->WorldPos.Z >> 8;
|
|
|
|
angle = Arctan(dx,-dz) + 1024;
|
|
angle &= 2047;
|
|
dangle = angle - p_person->Draw.Tweened->Angle;
|
|
dangle &= 2047;
|
|
|
|
return dangle;
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
SLONG get_fence_bottom(SLONG x, SLONG z, SLONG col)
|
|
{
|
|
SLONG fy;
|
|
|
|
if (dfacets[col].FacetFlags & FACET_FLAG_ONBUILDING||dfacets[col].FacetType==STOREY_TYPE_NORMAL)
|
|
{
|
|
fy = dfacets[col].Y[0];
|
|
}
|
|
else
|
|
{
|
|
fy = PAP_calc_height_at(x,z);
|
|
}
|
|
|
|
return fy; // + 20?
|
|
}
|
|
|
|
SLONG get_fence_top(SLONG x, SLONG z, SLONG col)
|
|
{
|
|
SLONG fy;
|
|
SLONG fheight;
|
|
SLONG ftop;
|
|
|
|
if (dfacets[col].FacetFlags & FACET_FLAG_ONBUILDING ||dfacets[col].FacetType==STOREY_TYPE_NORMAL)
|
|
{
|
|
fy = dfacets[col].Y[0];
|
|
}
|
|
else
|
|
{
|
|
fy = PAP_calc_height_at(x,z);
|
|
}
|
|
|
|
fheight = dfacets[col].Height * 64;
|
|
ftop = fy + fheight;
|
|
|
|
if (fheight == 0x100)
|
|
{
|
|
//
|
|
// You can jump over 1 high unclimbable fences. Pretend they
|
|
// are slightly higher!
|
|
//
|
|
|
|
if (dfacets[col].FacetFlags & FACET_FLAG_UNCLIMBABLE)
|
|
{
|
|
ftop += 0x40;
|
|
}
|
|
}
|
|
|
|
return ftop;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Makes a person create a splash.
|
|
//
|
|
|
|
void person_splash(
|
|
Thing *p_person,
|
|
SLONG limb) // -1 => Splash at the centre of the person.
|
|
{
|
|
|
|
#ifndef PSX
|
|
|
|
SLONG i,type;
|
|
|
|
SLONG foot_x;
|
|
SLONG foot_y;
|
|
SLONG foot_z;
|
|
|
|
SLONG track_x,track_y,track_z,dx,dy,dz;
|
|
|
|
SLONG splash_x;
|
|
SLONG splash_y;
|
|
SLONG splash_z;
|
|
|
|
|
|
if (limb == -1)
|
|
{
|
|
track_x = 0;
|
|
track_y = 0;
|
|
track_z = 0;
|
|
}
|
|
else
|
|
{
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
limb,
|
|
&track_x,
|
|
&track_y,
|
|
&track_z);
|
|
}
|
|
|
|
foot_x = track_x + (p_person->WorldPos.X >> 8);
|
|
foot_y = track_y + (p_person->WorldPos.Y >> 8);
|
|
foot_z = track_z + (p_person->WorldPos.Z >> 8);
|
|
|
|
#ifndef TARGET_DC
|
|
for (i = 0; i < 1; i++)
|
|
{
|
|
splash_x = foot_x + (Random() & 0x1f) - 0xf;
|
|
splash_y = foot_y;
|
|
splash_z = foot_z + (Random() & 0x1f) - 0xf;
|
|
|
|
DRIP_create_if_in_puddle(
|
|
splash_x,
|
|
splash_y,
|
|
splash_z);
|
|
}
|
|
|
|
PUDDLE_splash(
|
|
foot_x,
|
|
foot_y,
|
|
foot_z);
|
|
#endif
|
|
|
|
/*
|
|
if (GAME_FLAGS & GF_SEWERS) {
|
|
if ((p_person->Flags & FLAGS_IN_SEWERS) && (p_person->State != STATE_IDLE)) {
|
|
if (person_is_on(p_person)==PERSON_ON_WATER)
|
|
DRIP_create(foot_x,foot_y,foot_z);
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
// Add footprints
|
|
float yaw,pitch,roll;
|
|
float matrix[9], vector[3];
|
|
static int heh_heh_heh=-1;
|
|
|
|
|
|
if (limb==heh_heh_heh) return;
|
|
heh_heh_heh=limb;
|
|
|
|
yaw = -float(p_person->Draw.Tweened->Angle) * (2.0F * PI / 2048.0F);
|
|
pitch = -float(p_person->Draw.Tweened->Tilt) * (2.0F * PI / 2048.0F);
|
|
roll = -float(p_person->Draw.Tweened->Roll) * (2.0F * PI / 2048.0F);
|
|
|
|
MATRIX_calc(matrix, yaw, pitch, roll);
|
|
vector[2]=20; vector[1]=0; vector[0]=0;
|
|
MATRIX_MUL(matrix,vector[0],vector[1],vector[2]);
|
|
dx=vector[0]; dy=vector[1]; dz=vector[2];
|
|
|
|
if ((limb==SUB_OBJECT_RIGHT_FOOT)||(limb==-1)) {
|
|
type=TRACK_TYPE_RIGHT_PRINT;
|
|
|
|
// don't ask...
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_RIGHT_FOOT,
|
|
&track_x,
|
|
&track_y,
|
|
&track_z);
|
|
track_x<<=8;
|
|
track_y<<=8;
|
|
track_z<<=8;
|
|
track_x+=p_person->WorldPos.X;
|
|
track_z+=p_person->WorldPos.Z;
|
|
|
|
track_y=(PAP_calc_height_at_thing(p_person,track_x>>8,track_z>>8)<<8)+0x180;
|
|
|
|
{
|
|
SLONG mx,mz;
|
|
|
|
mx=(track_x-(dx*0x1ff))>>16;
|
|
mz=(track_z-(dz*0x1ff))>>16;
|
|
if(mx>=0 && mz<128 && mz>=0 && mz<128)
|
|
if(!(MAV_SPARE(mx ,mz) & MAV_SPARE_FLAG_WATER))
|
|
p_person->Genus.Person->muckyfootprint=TRACKS_Add(track_x-(dx*0x1ff),track_y-(dy*0x1ff),track_z-(dz*0x1ff),dx*2,dy*2,dz*2,type,p_person->Genus.Person->muckyfootprint);
|
|
}
|
|
}
|
|
if ((limb==SUB_OBJECT_LEFT_FOOT)||(limb==-1)) {
|
|
type=TRACK_TYPE_LEFT_PRINT;
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_LEFT_FOOT,
|
|
&track_x,
|
|
&track_y,
|
|
&track_z);
|
|
track_x<<=8;
|
|
track_y<<=8;
|
|
track_z<<=8;
|
|
track_x+=p_person->WorldPos.X;
|
|
track_z+=p_person->WorldPos.Z;
|
|
track_y=(PAP_calc_height_at_thing(p_person,track_x>>8,track_z>>8)<<8)+0x180;
|
|
|
|
{
|
|
SLONG mx,mz;
|
|
|
|
mx=(track_x-(dx*0x1ff))>>16;
|
|
mz=(track_z-(dz*0x1ff))>>16;
|
|
if(mx>=0 && mz<128 && mz>=0 && mz<128)
|
|
if(!(MAV_SPARE(mx ,mz) & MAV_SPARE_FLAG_WATER))
|
|
p_person->Genus.Person->muckyfootprint=TRACKS_Add(track_x-(dx*0x1ff),track_y-(dy*0x1ff),track_z-(dz*0x1ff),dx*2,dy*2,dz*2,type,p_person->Genus.Person->muckyfootprint);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
// Sets a person PersonID to the correct value for that person. It looks
|
|
// to see if they have a gun/item in use etc...
|
|
//
|
|
|
|
void set_persons_personid(Thing *p_person)
|
|
{
|
|
Thing *p_special;
|
|
|
|
if(p_person->Genus.Person->PersonType==PERSON_CIV)
|
|
return;
|
|
|
|
p_person->Draw.Tweened->PersonID &= 0x1f;
|
|
|
|
//
|
|
// Has this person got a pistol out?
|
|
//
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
p_person->Draw.Tweened->PersonID |= 1<<5;
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Using an item?
|
|
//
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
switch(p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_NONE:
|
|
case SPECIAL_KEY:
|
|
break;
|
|
|
|
case SPECIAL_GUN:
|
|
p_person->Draw.Tweened->PersonID |= 1<<5;
|
|
break;
|
|
|
|
case SPECIAL_HEALTH:
|
|
case SPECIAL_BOMB:
|
|
break;
|
|
|
|
case SPECIAL_SHOTGUN:
|
|
p_person->Draw.Tweened->PersonID |= 3<<5;
|
|
break;
|
|
|
|
case SPECIAL_KNIFE:
|
|
p_person->Draw.Tweened->PersonID |= 2<<5;
|
|
break;
|
|
|
|
case SPECIAL_EXPLOSIVES:
|
|
case SPECIAL_GRENADE:
|
|
break;
|
|
|
|
case SPECIAL_AK47:
|
|
p_person->Draw.Tweened->PersonID |= 5<<5;
|
|
break;
|
|
|
|
case SPECIAL_BASEBALLBAT:
|
|
p_person->Draw.Tweened->PersonID |= 4<<5;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
//---------------------------------------------------------------
|
|
|
|
//#define SHOW_ANIM_NUMS
|
|
|
|
// hopefully the compiler's smart enough (heh) to completely optimise out an empty inline function... :P
|
|
|
|
inline void ShowAnimNumber(SLONG anim) {
|
|
|
|
#ifdef SHOW_ANIM_NUMS
|
|
|
|
CBYTE str[100];
|
|
|
|
sprintf(str,"Anim %d",anim);
|
|
|
|
CONSOLE_text(str,4000);
|
|
|
|
#endif
|
|
}
|
|
|
|
void queue_anim(Thing *p_person,SLONG anim)
|
|
{
|
|
ASSERT(anim!=1);
|
|
// ASSERT(anim!=54);
|
|
ASSERT(((ULONG)global_anim_array[p_person->Genus.Person->AnimType][anim])>1000);
|
|
p_person->Genus.Person->Flags2&=~FLAG2_SYNC_SOUNDFX;
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_LOCK_ANIM_CHANGE)
|
|
{
|
|
locked_anim_change(p_person,0,anim);
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_LOCK_ANIM_CHANGE;
|
|
}
|
|
else
|
|
{
|
|
p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][anim];
|
|
}
|
|
p_person->Draw.Tweened->CurrentAnim = anim;
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
ASSERT(p_person->Draw.Tweened->CurrentFrame->FirstElement);
|
|
if(p_person->Draw.Tweened->NextFrame)
|
|
ASSERT(p_person->Draw.Tweened->NextFrame->FirstElement);
|
|
|
|
ShowAnimNumber(anim);
|
|
}
|
|
|
|
void tween_to_anim(Thing *p_person,SLONG anim)
|
|
{
|
|
// ASSERT(anim!=54);
|
|
p_person->Genus.Person->Flags2&=~FLAG2_SYNC_SOUNDFX;
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_LOCK_ANIM_CHANGE)
|
|
{
|
|
locked_anim_change(p_person,0,anim);
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_LOCK_ANIM_CHANGE;
|
|
}
|
|
else
|
|
{
|
|
p_person->Draw.Tweened->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][anim];
|
|
p_person->Draw.Tweened->QueuedFrame = 0;
|
|
}
|
|
|
|
p_person->Draw.Tweened->CurrentAnim = anim;
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
ASSERT(p_person->Draw.Tweened->CurrentFrame->FirstElement);
|
|
if(p_person->Draw.Tweened->NextFrame)
|
|
ASSERT(p_person->Draw.Tweened->NextFrame->FirstElement);
|
|
|
|
ShowAnimNumber(anim);
|
|
}
|
|
|
|
void set_anim(Thing *p_person,SLONG anim)
|
|
{
|
|
ASSERT(anim!=1);
|
|
// ASSERT(anim!=54);
|
|
/*
|
|
if(p_person->Genus.Person->PlayerID==0)
|
|
{
|
|
CBYTE str[100];
|
|
sprintf(str," fight %d
|
|
}
|
|
*/
|
|
p_person->Genus.Person->Flags2&=~FLAG2_SYNC_SOUNDFX;
|
|
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_LOCK_ANIM_CHANGE)
|
|
{
|
|
locked_anim_change(p_person,0,anim);
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_LOCK_ANIM_CHANGE;
|
|
}
|
|
else
|
|
{
|
|
p_person->Draw.Tweened->AnimTween = 0;
|
|
p_person->Draw.Tweened->QueuedFrame = 0;
|
|
p_person->Draw.Tweened->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][anim];
|
|
p_person->Draw.Tweened->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][anim]->NextFrame;
|
|
p_person->Draw.Tweened->Locked = 0;
|
|
}
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
p_person->Draw.Tweened->CurrentAnim = anim;
|
|
ASSERT(p_person->Draw.Tweened->CurrentFrame->FirstElement);
|
|
if(p_person->Draw.Tweened->NextFrame)
|
|
ASSERT(p_person->Draw.Tweened->NextFrame->FirstElement);
|
|
|
|
ShowAnimNumber(anim);
|
|
|
|
}
|
|
// set_anim_of_type(p_person,CIV_M_ANIM_WALK,ANIM_TYPE_CIV);
|
|
void set_anim_of_type(Thing *p_person,SLONG anim,SLONG type)
|
|
{
|
|
ASSERT(anim!=1);
|
|
// ASSERT(anim!=54);
|
|
/*
|
|
if(p_person->Genus.Person->PlayerID==0)
|
|
{
|
|
CBYTE str[100];
|
|
sprintf(str," fight %d
|
|
}
|
|
*/
|
|
p_person->Genus.Person->Flags2&=~FLAG2_SYNC_SOUNDFX;
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_LOCK_ANIM_CHANGE;
|
|
/*
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_LOCK_ANIM_CHANGE)
|
|
{
|
|
locked_anim_change(p_person,0,anim);
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_LOCK_ANIM_CHANGE;
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
p_person->Draw.Tweened->AnimTween = 0;
|
|
p_person->Draw.Tweened->QueuedFrame = 0;
|
|
// p_person->Draw.Tweened->CurrentFrame = global_anim_array[type][anim];
|
|
// p_person->Draw.Tweened->NextFrame = global_anim_array[type][anim]->NextFrame;
|
|
p_person->Draw.Tweened->CurrentFrame = game_chunk[type].AnimList[anim];
|
|
p_person->Draw.Tweened->NextFrame = game_chunk[type].AnimList[anim]->NextFrame;
|
|
}
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
p_person->Draw.Tweened->CurrentAnim = anim;
|
|
ASSERT(p_person->Draw.Tweened->CurrentFrame->FirstElement);
|
|
if(p_person->Draw.Tweened->NextFrame)
|
|
ASSERT(p_person->Draw.Tweened->NextFrame->FirstElement);
|
|
|
|
ShowAnimNumber(anim);
|
|
|
|
}
|
|
|
|
void set_locked_anim(Thing *p_person,SLONG anim,SLONG sub_object)
|
|
{
|
|
ASSERT(anim!=1);
|
|
ASSERT(anim);
|
|
// ASSERT(anim!=54);
|
|
p_person->Genus.Person->Flags2&=~FLAG2_SYNC_SOUNDFX;
|
|
locked_anim_change(p_person,sub_object,anim);
|
|
p_person->Draw.Tweened->AnimTween = 0;
|
|
p_person->Draw.Tweened->QueuedFrame = 0;
|
|
p_person->Draw.Tweened->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][anim];
|
|
p_person->Draw.Tweened->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][anim]->NextFrame;
|
|
p_person->Draw.Tweened->CurrentAnim = anim;
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
|
|
ShowAnimNumber(anim);
|
|
|
|
}
|
|
void set_locked_anim_angle(Thing *p_person,SLONG anim,SLONG sub_object,SLONG dangle)
|
|
{
|
|
ASSERT(anim!=1);
|
|
ASSERT(anim);
|
|
// ASSERT(anim!=54);
|
|
p_person->Genus.Person->Flags2&=~FLAG2_SYNC_SOUNDFX;
|
|
locked_anim_change(p_person,sub_object,anim,dangle);
|
|
p_person->Draw.Tweened->AnimTween = 0;
|
|
p_person->Draw.Tweened->QueuedFrame = 0;
|
|
p_person->Draw.Tweened->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][anim];
|
|
p_person->Draw.Tweened->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][anim]->NextFrame;
|
|
p_person->Draw.Tweened->CurrentAnim = anim;
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
|
|
ShowAnimNumber(anim);
|
|
|
|
}
|
|
void set_locked_anim_of_type(Thing *p_person,SLONG anim,SLONG sub_object)
|
|
{
|
|
ASSERT(anim!=1);
|
|
ASSERT(anim);
|
|
// ASSERT(anim!=54);
|
|
p_person->Genus.Person->Flags2&=~FLAG2_SYNC_SOUNDFX;
|
|
locked_anim_change(p_person,sub_object,anim);
|
|
p_person->Draw.Tweened->AnimTween = 0;
|
|
p_person->Draw.Tweened->QueuedFrame = 0;
|
|
p_person->Draw.Tweened->CurrentFrame = game_chunk[p_person->Genus.Person->AnimType].AnimList[anim];
|
|
p_person->Draw.Tweened->NextFrame = game_chunk[p_person->Genus.Person->AnimType].AnimList[anim]->NextFrame;
|
|
p_person->Draw.Tweened->CurrentAnim = anim;
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
|
|
ShowAnimNumber(anim);
|
|
|
|
}
|
|
|
|
SLONG get_cable_sdist_from_end(SLONG facet,SLONG ax,SLONG az)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
|
|
SLONG x1;
|
|
SLONG z1;
|
|
|
|
|
|
SLONG d1;
|
|
|
|
struct DFacet *p_facet;
|
|
|
|
p_facet=&dfacets[facet];
|
|
|
|
|
|
|
|
|
|
if(p_facet->Y[0] >p_facet->Y[1])
|
|
{
|
|
x1=p_facet->x[1] << 8;
|
|
z1=p_facet->z[1] << 8;
|
|
|
|
dx = x1 - ax;
|
|
dz = z1 - az;
|
|
|
|
d1=dx*dx+dz*dz;
|
|
}
|
|
else
|
|
{
|
|
x1=p_facet->x[0] << 8;
|
|
z1=p_facet->z[0] << 8;
|
|
|
|
dx = x1 - ax;
|
|
dz = z1 - az;
|
|
|
|
d1=dx*dx+dz*dz;
|
|
}
|
|
|
|
return(d1);
|
|
}
|
|
|
|
void person_death_slide(Thing *p_person)
|
|
{
|
|
SLONG dx,dy=0,dz;
|
|
SLONG along;
|
|
SLONG dist,sdist;
|
|
|
|
GameCoord new_position = p_person->WorldPos;
|
|
|
|
dist=p_person->Velocity >> 2;
|
|
|
|
dx =- (SIN(p_person->Draw.Tweened->Angle)*dist)>>8;
|
|
dz =- (COS(p_person->Draw.Tweened->Angle)*dist)>>8;
|
|
dx = (dx*TICK_RATIO)>>TICK_SHIFT;
|
|
dz = (dz*TICK_RATIO)>>TICK_SHIFT;
|
|
|
|
along = get_cable_along(p_person->Genus.Person->OnFacet,(p_person->WorldPos.X>>8)+(dx>>8),(p_person->WorldPos.Z>>8)+(dz>>8));
|
|
sdist = get_cable_sdist_from_end(p_person->Genus.Person->OnFacet,(p_person->WorldPos.X>>8)+(dx>>8),(p_person->WorldPos.Z>>8)+(dz>>8));
|
|
|
|
#define CABLE_START (1 * CABLE_ALONG_MAX >> 8)
|
|
#define CABLE_END (245 * CABLE_ALONG_MAX >> 8)
|
|
|
|
//
|
|
// only really needs the new sdist method, but keep old one for backwards compatability
|
|
//
|
|
if (WITHIN(along, CABLE_START, CABLE_END) && sdist>64*64)
|
|
{
|
|
//
|
|
// Still on the cable.
|
|
//
|
|
|
|
MFX_play_ambient(THING_NUMBER(p_person), S_ZIPWIRE, MFX_LOOPED | MFX_NEVER_OVERLAP);
|
|
MFX_set_pitch(THING_NUMBER(p_person), S_ZIPWIRE, 224 + (p_person->Velocity / 4));
|
|
|
|
new_position.X += dx;
|
|
new_position.Z += dz;
|
|
move_thing_on_map(p_person, &new_position);
|
|
|
|
do_person_on_cable(p_person);
|
|
}
|
|
else
|
|
{
|
|
MFX_stop(THING_NUMBER(p_person), S_ZIPWIRE);
|
|
|
|
set_person_drop_down(p_person,PERSON_DROP_DOWN_OFF_FACE);
|
|
|
|
return;
|
|
|
|
//p_person->SubState=SUB_STATE_DANGLING_CABLE;
|
|
//p_person->Velocity=0;
|
|
//p_person->DeltaVelocity=0;
|
|
//p_person->Genus.Person->Action=ACTION_DANGLING_CABLE;
|
|
//locked_anim_change(p_person,SUB_OBJECT_LEFT_HAND,ANIM_HAND_OVER_HAND);
|
|
}
|
|
}
|
|
|
|
/*
|
|
|
|
//
|
|
// big drop
|
|
//
|
|
void set_person_dead_land(Thing *p_thing)
|
|
{
|
|
DrawTween *draw_info;
|
|
WaveParams die;
|
|
|
|
|
|
draw_info=p_thing->Draw.Tweened;
|
|
draw_info->CurrentFrame = global_anim_array[p_thing->Genus.Person->AnimType][ANIM_FATAL_FALL];
|
|
|
|
// Set up the wave params.
|
|
die.Priority = 0;
|
|
die.Flags = WAVE_CARTESIAN;
|
|
die.Mode.Cartesian.Scale = (128<<8);
|
|
die.Mode.Cartesian.X = p_thing->WorldPos.X;
|
|
die.Mode.Cartesian.Y = p_thing->WorldPos.Y;
|
|
die.Mode.Cartesian.Z = p_thing->WorldPos.Z;
|
|
|
|
switch(p_thing->Genus.Person->AnimType)
|
|
{
|
|
case PERSON_COP:
|
|
// PlayWave(THING_NUMBER(p_thing),S_MALE_DIE_2,WAVE_PLAY_NO_INTERUPT,&die);
|
|
play_quick_wave_xyz(p_thing->WorldPos.X,p_thing->WorldPos.Y,p_thing->WorldPos.Z,
|
|
S_MALE_DIE_2,0,0);
|
|
break;
|
|
case PERSON_DARCI:
|
|
// PlayWave(THING_NUMBER(p_thing),S_FEMALE_DIE_2,WAVE_PLAY_NO_INTERUPT,&die);
|
|
play_quick_wave_xyz(p_thing->WorldPos.X,p_thing->WorldPos.Y,p_thing->WorldPos.Z,
|
|
S_FEMALE_DIE_2,0,0);
|
|
break;
|
|
}
|
|
set_person_dying(p_thing);
|
|
draw_info->NextFrame = draw_info->CurrentFrame->NextFrame;
|
|
draw_info->QueuedFrame = 0; //draw_info->CurrentFrame->NextFrame;
|
|
draw_info->AnimTween = 0;
|
|
draw_info->CurrentAnim = ANIM_KO_BACK;
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
void emergency_uncarry(Thing *p_person);
|
|
SLONG people_allowed_to_hit_each_other(Thing *p_victim,Thing *p_agressor);
|
|
|
|
void sweep_feet(Thing *p_person,Thing *p_aggressor,SLONG death_type)
|
|
{
|
|
SlideSoundCheck(p_person,1);
|
|
|
|
if (p_person->State == STATE_JUMPING)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (p_person->State == STATE_DANGLING)
|
|
{
|
|
if (p_person->SubState == SUB_STATE_DROP_DOWN)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (p_person->Genus.Person->Flags2 & FLAG2_PERSON_CARRYING)
|
|
{
|
|
emergency_uncarry(p_person);
|
|
}
|
|
|
|
if(!people_allowed_to_hit_each_other(p_person,p_aggressor))
|
|
{
|
|
//
|
|
// Your chums jump to avoid your attack
|
|
//
|
|
|
|
set_person_standing_jump(p_person);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (PersonIsMIB(p_person))
|
|
{
|
|
//
|
|
// Men In Black jump to avoid the attack like ninjas!
|
|
//
|
|
|
|
set_person_standing_jump(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
if (PersonIsMIB(p_person))
|
|
{
|
|
|
|
}
|
|
|
|
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_FIGHT_TEST && (p_person->Genus.Person->pcom_ai_other & PCOM_COMBAT_SLIDE))
|
|
{
|
|
//
|
|
// Fight test dummies who are set to die when their feet are
|
|
// swept die even if they are invulnerable...
|
|
//
|
|
|
|
p_person->Genus.Person->Health = 0;
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->Flags2 & FLAG2_PERSON_INVULNERABLE)
|
|
{
|
|
//
|
|
// Invulnerable people jump.
|
|
//
|
|
|
|
set_person_standing_jump(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
{
|
|
SLONG r,prob;
|
|
prob=40+(GET_SKILL(p_person)<<3);
|
|
if((r=(Random()%160))<prob)
|
|
{
|
|
//
|
|
//
|
|
// Somone tried to slide attack you
|
|
if(can_a_see_b(p_person,p_aggressor,-1,1))
|
|
{
|
|
PCOM_attack_happened(p_person, p_aggressor);
|
|
set_person_standing_jump(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
}
|
|
/* else
|
|
{
|
|
TRACE(" %d !<%d\n",r,prob);
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
|
|
if ((p_person->Genus.Person->pcom_bent & PCOM_BENT_PLAYERKILL) && !p_aggressor->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// Only the player can hurt this person
|
|
//
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->Flags2 & FLAG2_PERSON_INVULNERABLE)
|
|
{
|
|
//
|
|
// Nothing hurts this person.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
if(!p_person->Genus.Person->PlayerID)
|
|
p_person->Genus.Person->Health -= 49;
|
|
#ifdef PSX
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
PSX_SetShock(1,128);
|
|
}
|
|
#endif
|
|
#ifdef TARGET_DC
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
Vibrate ( 20.0f, 1.0f, 0.25f );
|
|
}
|
|
#endif
|
|
// add_damage_value_thing(p_person,49>>1);
|
|
}
|
|
|
|
if (p_person->Genus.Person->Health <= 0)
|
|
{
|
|
p_person->Genus.Person->Health = 0;
|
|
death_type = PERSON_DEATH_TYPE_OTHER;
|
|
|
|
if (p_aggressor)
|
|
{
|
|
p_aggressor->Genus.Person->Flags2 |= FLAG2_PERSON_IS_MURDERER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
death_type = PERSON_DEATH_TYPE_LEG_SWEEP;
|
|
}
|
|
|
|
//
|
|
// Tell the AI system whats going on.
|
|
//
|
|
|
|
PCOM_attack_happened(p_person, p_aggressor);
|
|
|
|
set_person_dead(p_person,p_aggressor,death_type,0,0);
|
|
}
|
|
|
|
//
|
|
// Returns TRUE if there is room behind the person for him to die
|
|
// in the given direction.
|
|
//
|
|
|
|
SLONG is_there_room_behind_person(Thing *p_person, SLONG hit_from_behind)
|
|
{
|
|
ULONG los_flag;
|
|
|
|
//
|
|
// A vector in the direction this person is going to die in.
|
|
//
|
|
|
|
SLONG dx = SIN(p_person->Draw.Tweened->Angle);
|
|
SLONG dz = COS(p_person->Draw.Tweened->Angle);
|
|
|
|
if (hit_from_behind)
|
|
{
|
|
dx = -dx;
|
|
dz = -dz;
|
|
}
|
|
|
|
SLONG h1 = PAP_calc_map_height_at(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
|
|
SLONG h2 = PAP_calc_map_height_at(
|
|
p_person->WorldPos.X + dx >> 8,
|
|
p_person->WorldPos.Z + dz >> 8);
|
|
|
|
if (abs(h2 - h1) > 0x40)
|
|
{
|
|
//
|
|
// No room to die this way round.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure there is enough room in this direction.
|
|
//
|
|
|
|
los_flag = LOS_FLAG_IGNORE_SEETHROUGH_FENCE_FLAG | LOS_FLAG_INCLUDE_CARS;
|
|
|
|
if (p_person->Genus.Person->Ware)
|
|
{
|
|
//
|
|
// Don't do the underground check if the person is in a warehouse.
|
|
//
|
|
|
|
los_flag |= LOS_FLAG_IGNORE_UNDERGROUND_CHECK;
|
|
}
|
|
|
|
/*
|
|
|
|
AENG_world_line(
|
|
(p_person->WorldPos.X >> 8),
|
|
(p_person->WorldPos.Y + 0x3000 >> 8),
|
|
(p_person->WorldPos.Z >> 8),
|
|
20,
|
|
0xffffff,
|
|
(p_person->WorldPos.X + dx >> 8),
|
|
(p_person->WorldPos.Y + 0x3000 >> 8),
|
|
(p_person->WorldPos.Z + dz >> 8),
|
|
0,
|
|
0,
|
|
TRUE);
|
|
|
|
*/
|
|
|
|
if (!there_is_a_los(
|
|
(p_person->WorldPos.X >> 8),
|
|
(p_person->WorldPos.Y + 0x3000 >> 8),
|
|
(p_person->WorldPos.Z >> 8),
|
|
(p_person->WorldPos.X + dx >> 8),
|
|
(p_person->WorldPos.Y + 0x3000 >> 8),
|
|
(p_person->WorldPos.Z + dz >> 8),
|
|
los_flag)) // No underground check incase this is inside a warehouse...
|
|
{
|
|
//
|
|
// No room to die this way round.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
extern SLONG slide_along(SLONG x1, SLONG y1, SLONG z1,SLONG *x2, SLONG *y2, SLONG *z2,SLONG extra_wall_height,SLONG radius,ULONG flags);
|
|
void set_fence_hole(struct DFacet *p_facet,SLONG pos);
|
|
|
|
SLONG get_along_facet(SLONG x,SLONG z,SLONG colvect)
|
|
{
|
|
DFacet *p_facet;
|
|
SLONG dx,dz;
|
|
SLONG along;
|
|
|
|
p_facet=&dfacets[colvect];
|
|
|
|
dx=p_facet->x[1]-p_facet->x[0];
|
|
dz=p_facet->z[1]-p_facet->z[0];
|
|
|
|
if(dx)
|
|
{
|
|
along=x-(p_facet->x[0]<<8);
|
|
along=along/dx;
|
|
}
|
|
else
|
|
{
|
|
along=z-(p_facet->z[0]<<8);
|
|
along=along/dz;
|
|
}
|
|
|
|
return(along);
|
|
}
|
|
#ifdef UNUSED_WIRECUTTERS
|
|
extern UWORD fence_colvect;
|
|
SLONG set_person_cut_fence(Thing *p_person)
|
|
{
|
|
SLONG x1,y1,z1,x2,y2,z2,dx,dz;
|
|
SLONG along;
|
|
|
|
|
|
dx =- (SIN(p_person->Draw.Tweened->Angle)*50)>>8;
|
|
dz =- (COS(p_person->Draw.Tweened->Angle)*50)>>8;
|
|
|
|
x1=p_person->WorldPos.X;
|
|
y1=p_person->WorldPos.Y;
|
|
z1=p_person->WorldPos.Z;
|
|
|
|
x2=x1+dx;
|
|
z2=z1+dz;
|
|
y2=y1;
|
|
|
|
|
|
slide_along(x1,y1,z1,&x2,&y2,&z2,0,50,0);
|
|
|
|
if(fence_colvect)
|
|
{
|
|
// we have hit a fence colvect
|
|
|
|
along=get_along_facet(x1>>8,z1>>8,fence_colvect);
|
|
|
|
if(along>0&&along<255)
|
|
{
|
|
|
|
set_fence_hole(&dfacets[fence_colvect],along);
|
|
set_person_croutch(p_person);
|
|
return(1);
|
|
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
#endif
|
|
void set_person_dead(
|
|
Thing *p_thing,
|
|
Thing *p_aggressor,
|
|
SLONG death_type,
|
|
SLONG behind,
|
|
SLONG height)
|
|
{
|
|
DrawTween *draw_info;
|
|
#ifndef PSX
|
|
WaveParams die;
|
|
#endif
|
|
SLONG anim;
|
|
SLONG substate;
|
|
SLONG quick = FALSE;
|
|
SLONG locked = FALSE;
|
|
|
|
ASSERT(p_thing->Class == CLASS_PERSON);
|
|
p_thing->Draw.Tweened->Roll = 0;
|
|
p_thing->Draw.Tweened->DRoll = 0;
|
|
|
|
p_thing->Genus.Person->InsideRoom=0;
|
|
|
|
if (p_thing->Genus.Person->Flags2 & FLAG2_PERSON_CARRYING)
|
|
{
|
|
emergency_uncarry(p_thing);
|
|
}
|
|
|
|
|
|
// ASSERT(is_there_room_behind_person(p_thing, behind));
|
|
|
|
#ifdef BIKE
|
|
|
|
//
|
|
// If you've come off a bike...
|
|
//
|
|
|
|
if (p_thing->Genus.Person->Flags & FLAG_PERSON_BIKING)
|
|
{
|
|
//
|
|
// Knocked off your bike...
|
|
//
|
|
|
|
BIKE_set_parked(TO_THING(p_thing->Genus.Person->InCar));
|
|
|
|
p_thing->Genus.Person->Flags &= ~FLAG_PERSON_BIKING;
|
|
p_thing->Genus.Person->InCar = 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Tell the PCOM brain what has happened.
|
|
//
|
|
|
|
if (p_thing->Genus.Person->PlayerID==0)
|
|
{
|
|
//
|
|
// Non players
|
|
//
|
|
|
|
PCOM_knockdown_happened(p_thing);
|
|
}
|
|
|
|
if (p_aggressor && p_aggressor->Genus.Person->PlayerID)
|
|
{
|
|
if (death_type != PERSON_DEATH_TYPE_LEG_SWEEP &&
|
|
death_type != PERSON_DEATH_TYPE_STAY_ALIVE &&
|
|
death_type != PERSON_DEATH_TYPE_GET_DOWN &&
|
|
death_type != PERSON_DEATH_TYPE_STAY_ALIVE_PRONE)
|
|
{
|
|
//
|
|
// The player caused the death...
|
|
//
|
|
|
|
switch(p_thing->Genus.Person->PersonType)
|
|
{
|
|
case PERSON_THUG_RASTA:
|
|
case PERSON_THUG_GREY:
|
|
case PERSON_THUG_RED:
|
|
case PERSON_MIB1:
|
|
case PERSON_MIB2:
|
|
case PERSON_MIB3:
|
|
stat_killed_thug++;
|
|
break;
|
|
default:
|
|
stat_killed_innocent++;
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
if ((p_thing->Genus.Person->pcom_ai == PCOM_AI_CIV && p_thing->Genus.Person->pcom_move == PCOM_MOVE_WANDER) ||
|
|
(p_thing->Genus.Person->PersonType == PERSON_COP))
|
|
{
|
|
if (!(p_thing->Genus.Person->Flags2 & FLAG2_PERSON_GUILTY))
|
|
{
|
|
//
|
|
// ...of an innocent!
|
|
//
|
|
|
|
NET_PLAYER(0)->Genus.Player->RedMarks += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_thing->SubState == SUB_STATE_GRAPPLE_HELD)
|
|
{
|
|
//
|
|
// set person holding me to fight idle
|
|
//
|
|
|
|
if(TO_THING(p_thing->Genus.Person->Target)->SubState!=SUB_STATE_GRAPPLE_ATTACK)
|
|
{
|
|
set_person_fight_idle(TO_THING(p_thing->Genus.Person->Target));
|
|
}
|
|
}
|
|
|
|
if(death_type!=PERSON_DEATH_TYPE_STAY_ALIVE && death_type!=PERSON_DEATH_TYPE_STAY_ALIVE_PRONE &&death_type!=PERSON_DEATH_TYPE_LEG_SWEEP)
|
|
{
|
|
if(p_thing->Genus.Person->Target)
|
|
{
|
|
remove_from_gang_attack(p_thing,TO_THING(p_thing->Genus.Person->Target));
|
|
}
|
|
if(p_aggressor)
|
|
{
|
|
remove_from_gang_attack(p_thing,p_aggressor);
|
|
if(p_aggressor->Genus.Person->Target==THING_NUMBER(p_thing))
|
|
{
|
|
//ASSERT(0);
|
|
extern UWORD find_target_from_gang(Thing *p_target);
|
|
p_aggressor->Genus.Person->Target=find_target_from_gang(p_aggressor);
|
|
if(p_aggressor->Genus.Person->PlayerID)
|
|
if(p_aggressor->Genus.Person->Target==0)
|
|
{
|
|
//
|
|
// nobody is attacking me so leave fight mode
|
|
//
|
|
p_aggressor->Genus.Person->Mode=PERSON_MODE_RUN;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if(p_thing->SubState==SUB_STATE_GRAPPLE_HOLD||p_thing->SubState==SUB_STATE_GRAPPLE_ATTACK)
|
|
{
|
|
//
|
|
// die while grappleing, hmmmmmm
|
|
//
|
|
|
|
//
|
|
// better let go of person we are grappelling
|
|
//
|
|
|
|
set_person_fight_idle(TO_THING(p_thing->Genus.Person->Target));
|
|
// return;
|
|
}
|
|
|
|
#define MAX_KNOCK_DOWN 6
|
|
|
|
static UBYTE knock_down[MAX_KNOCK_DOWN] =
|
|
{
|
|
ANIM_KD_FRONT_LOW,
|
|
ANIM_KD_FRONT_MID,
|
|
ANIM_KD_FRONT_HI,
|
|
ANIM_KD_BACK_LOW,
|
|
ANIM_KD_BACK_MID,
|
|
ANIM_KD_BACK_HI
|
|
};
|
|
|
|
ASSERT(p_thing->Class == CLASS_PERSON);
|
|
|
|
//
|
|
// Ignore people who are already dead.
|
|
//
|
|
|
|
if(death_type!=PERSON_DEATH_TYPE_PRONE && death_type!=PERSON_DEATH_TYPE_COMBAT_PRONE)
|
|
{
|
|
if (p_thing->State == STATE_DEAD ||
|
|
p_thing->State == STATE_DYING)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (p_thing->State == STATE_DYING &&
|
|
p_thing->SubState == SUB_STATE_DYING_FINAL_ANI)
|
|
{
|
|
//
|
|
// As good as dead already...
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Which anim shall we do?
|
|
//
|
|
|
|
switch(death_type)
|
|
{
|
|
case PERSON_DEATH_TYPE_PRONE:
|
|
|
|
//
|
|
// Already lay on floor.
|
|
//
|
|
|
|
substate = SUB_STATE_DYING_ACTUALLY_DIE;
|
|
p_thing->Genus.Person->Flags &= ~(FLAG_PERSON_KO | FLAG_PERSON_HELPLESS);
|
|
|
|
//
|
|
// If (quick) then we don't set an anim or play
|
|
// a sound effect.
|
|
//
|
|
|
|
quick = TRUE;
|
|
|
|
break;
|
|
|
|
case PERSON_DEATH_TYPE_COMBAT_PRONE:
|
|
|
|
//
|
|
// Person already lay down
|
|
//
|
|
|
|
substate = SUB_STATE_DYING_FINAL_ANI;
|
|
p_thing->Genus.Person->Flags &= ~(FLAG_PERSON_KO | FLAG_PERSON_HELPLESS);
|
|
|
|
//
|
|
// We must do a locked anim change.
|
|
//
|
|
|
|
locked = TRUE;
|
|
|
|
//
|
|
// Is this person on their front or back?
|
|
//
|
|
|
|
switch(person_is_lying_on_what(p_thing))
|
|
{
|
|
case PERSON_ON_HIS_FRONT:
|
|
anim = ANIM_FIGHT_STOMPED_BACK;
|
|
break;
|
|
|
|
case PERSON_ON_HIS_BACK:
|
|
anim = ANIM_FIGHT_STOMPED_FRONT;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case PERSON_DEATH_TYPE_SHOT_PISTOL:
|
|
case PERSON_DEATH_TYPE_SHOT_SHOTGUN:
|
|
case PERSON_DEATH_TYPE_SHOT_AK47:
|
|
|
|
{
|
|
static UWORD shoot_dead_anim[3] =
|
|
{
|
|
ANIM_SHOT_DEAD_HEAD,
|
|
ANIM_SHOT_DEAD_GUT,
|
|
ANIM_SHOT_DEAD_CHEST,
|
|
};
|
|
/*
|
|
if (!is_there_room_behind_person(p_thing, behind))
|
|
{
|
|
behind = !behind;
|
|
}
|
|
*/
|
|
if (!behind)
|
|
{
|
|
anim = ANIM_SHOT_DEAD_BACK;
|
|
}
|
|
else
|
|
{
|
|
anim = shoot_dead_anim[Random() % 3];
|
|
}
|
|
|
|
substate = SUB_STATE_DYING_FINAL_ANI;
|
|
p_thing->Genus.Person->Flags&=~FLAG_PERSON_KO;
|
|
}
|
|
|
|
break;
|
|
|
|
case PERSON_DEATH_TYPE_COMBAT:
|
|
|
|
ASSERT(WITHIN(behind, 0, 1));
|
|
ASSERT(WITHIN(height, 0, 2));
|
|
|
|
ASSERT(WITHIN(behind*3+height, 0, MAX_KNOCK_DOWN - 1));
|
|
|
|
//
|
|
// Make sure that this person is not going to die 'through' a
|
|
// building or a fence.
|
|
//
|
|
/*
|
|
if (!is_there_room_behind_person(p_thing, behind))
|
|
{
|
|
behind = !behind;
|
|
}
|
|
*/
|
|
|
|
anim = knock_down[behind*3+height];
|
|
substate = SUB_STATE_DYING_INITIAL_ANI;
|
|
|
|
break;
|
|
|
|
case PERSON_DEATH_TYPE_LAND:
|
|
|
|
switch(p_thing->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_PLUNGE_START:
|
|
case ANIM_PLUNGE_FORWARDS:
|
|
anim = ANIM_PLUNGE_FRONT_SLAM;
|
|
//#ifndef VERSION_GERMAN
|
|
if(VIOLENCE)
|
|
PYRO_create(p_thing->WorldPos,PYRO_SPLATTERY);
|
|
//#endif
|
|
// p_thing->WorldPos.Y += 0x8; // !
|
|
break;
|
|
|
|
default:
|
|
// anim = ANIM_FATAL_FALL;
|
|
anim = ANIM_BIGLAND_DIE;
|
|
break;
|
|
}
|
|
|
|
StopScreamFallSound(p_thing); // just in case
|
|
locked = TRUE;
|
|
substate = SUB_STATE_DYING_FINAL_ANI;
|
|
|
|
break;
|
|
|
|
case PERSON_DEATH_TYPE_OTHER:
|
|
|
|
//
|
|
// Is this person on the ground?
|
|
//
|
|
|
|
{
|
|
SLONG ground;
|
|
SLONG dy;
|
|
|
|
ground = PAP_calc_height_at_thing(p_thing,p_thing->WorldPos.X >> 8, p_thing->WorldPos.Z >> 8);
|
|
dy = (p_thing->WorldPos.Y >> 8) - ground;
|
|
|
|
if (dy < 0x20)
|
|
{
|
|
//
|
|
// On the ground.
|
|
//
|
|
|
|
anim = (behind) ? ANIM_KO_BEHIND_BIG : ANIM_KO_BACK;
|
|
substate = SUB_STATE_DYING_FINAL_ANI;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// In the air.
|
|
//
|
|
|
|
anim = ANIM_KD_FRONT_HI;
|
|
substate = SUB_STATE_DYING_INITIAL_ANI;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case PERSON_DEATH_TYPE_GET_DOWN:
|
|
set_anim(p_thing,ANIM_HANDS_UP_LIE);
|
|
p_thing->Genus.Person->Flags |= FLAG_PERSON_KO | FLAG_PERSON_HELPLESS;
|
|
substate = SUB_STATE_DYING_KNOCK_DOWN;
|
|
// substate = SUB_STATE_DYING_INITIAL_ANI;
|
|
p_thing->Genus.Person->Timer1 = 0;
|
|
|
|
//
|
|
// If (quick) then we don't set an animation going or
|
|
// play a sound effect
|
|
//
|
|
|
|
quick = TRUE;
|
|
break;
|
|
|
|
case PERSON_DEATH_TYPE_STAY_ALIVE_PRONE:
|
|
|
|
p_thing->Genus.Person->Flags |= FLAG_PERSON_KO | FLAG_PERSON_HELPLESS;
|
|
substate = SUB_STATE_DYING_KNOCK_DOWN;
|
|
p_thing->Genus.Person->Timer1 = 0;
|
|
|
|
//
|
|
// If (quick) then we don't set an animation going or
|
|
// play a sound effect
|
|
//
|
|
|
|
quick = TRUE;
|
|
|
|
break;
|
|
|
|
case PERSON_DEATH_TYPE_STAY_ALIVE:
|
|
|
|
|
|
//
|
|
// Is this person on the ground?
|
|
//
|
|
|
|
{
|
|
SLONG ground;
|
|
SLONG dy;
|
|
|
|
ground = PAP_calc_height_at_thing(p_thing,p_thing->WorldPos.X >> 8, p_thing->WorldPos.Z >> 8);
|
|
dy = (p_thing->WorldPos.Y >> 8) - ground;
|
|
|
|
p_thing->Genus.Person->Flags |= FLAG_PERSON_KO | FLAG_PERSON_HELPLESS;
|
|
|
|
if (dy < 0x20)
|
|
{
|
|
//
|
|
// On the ground.
|
|
//
|
|
|
|
substate = SUB_STATE_DYING_KNOCK_DOWN;
|
|
anim = (behind) ? ANIM_KO_BEHIND_BIG : ANIM_KO_BACK;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// In the air.
|
|
//
|
|
|
|
anim = ANIM_KD_FRONT_HI;
|
|
substate = SUB_STATE_DYING_INITIAL_ANI;
|
|
}
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case PERSON_DEATH_TYPE_LEG_SWEEP:
|
|
anim = ANIM_KD_BACK_LOW;
|
|
substate = SUB_STATE_DYING_INITIAL_ANI;
|
|
p_thing->Genus.Person->Flags |= FLAG_PERSON_KO | FLAG_PERSON_HELPLESS;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Make the person do the correct animation for the height
|
|
// at which the attack occured.
|
|
//
|
|
|
|
if(!quick)
|
|
{
|
|
if(locked)
|
|
{
|
|
set_locked_anim(p_thing,anim,0);
|
|
}
|
|
else
|
|
{
|
|
set_anim(p_thing,anim);
|
|
}
|
|
|
|
switch(p_thing->Genus.Person->PersonType)
|
|
{
|
|
case PERSON_COP:
|
|
MFX_play_xyz(0,S_MALE_DIE_2,0,p_thing->WorldPos.X,p_thing->WorldPos.Y,p_thing->WorldPos.Z);
|
|
break;
|
|
case PERSON_DARCI:
|
|
switch(death_type)
|
|
{
|
|
case HIT_TYPE_GUN_SHOT_H:
|
|
case HIT_TYPE_GUN_SHOT_M:
|
|
case HIT_TYPE_GUN_SHOT_L:
|
|
default:
|
|
MFX_play_xyz(0,S_FEMALE_DIE_2,0,p_thing->WorldPos.X,p_thing->WorldPos.Y,p_thing->WorldPos.Z);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the person die.
|
|
//
|
|
|
|
set_person_dying(p_thing, substate);
|
|
|
|
//
|
|
// If we know who killed us...
|
|
//
|
|
|
|
if (p_aggressor)
|
|
{
|
|
p_aggressor->Genus.Person->InWay = NULL;
|
|
|
|
if(p_aggressor->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// Its a player so keep score
|
|
//
|
|
|
|
GAME_SCORE(p_aggressor->Genus.Person->PlayerID-1) += 50;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// 0 is not guilty, 1 is a bit guilty, 2 is very guilty , 3 is top ten most wanted
|
|
//
|
|
SLONG is_person_guilty(Thing *p_person)
|
|
{
|
|
if(p_person->Genus.Person->Flags2&FLAG2_PERSON_GUILTY)
|
|
return(1);
|
|
|
|
if(p_person->Genus.Person->PersonType == PERSON_THUG_RASTA ||
|
|
p_person->Genus.Person->PersonType == PERSON_THUG_RED ||
|
|
// p_person->Genus.Person->PersonType == PERSON_TRAMP ||
|
|
p_person->Genus.Person->PersonType == PERSON_THUG_GREY)
|
|
{
|
|
return(2);
|
|
}
|
|
|
|
/* if(p_person->Genus.Person->PersonType == PERSON_MIB1)
|
|
return(3);
|
|
|
|
if(p_person->Genus.Person->PersonType == PERSON_MIB2)
|
|
return(3);
|
|
if(p_person->Genus.Person->PersonType == PERSON_MIB3)
|
|
return(3);*/
|
|
if (PersonIsMIB(p_person)) return 3;
|
|
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_GUARD ||
|
|
p_person->Genus.Person->pcom_ai == PCOM_AI_GANG)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
SLONG person_on_floor(Thing *p_person)
|
|
{
|
|
if(p_person->SubState==SUB_STATE_RUNNING||p_person->SubState==SUB_STATE_WALKING||p_person->State==STATE_IDLE||p_person->State==STATE_CIRCLING||p_person->State==STATE_GUN||p_person->State==STATE_HIT_RECOIL)
|
|
{
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// climbing ladders, jumping, doing stuff that may take you off the floor
|
|
//
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
SLONG really_on_floor(Thing *p_person)
|
|
{
|
|
SLONG foot_x;
|
|
SLONG foot_y;
|
|
SLONG foot_z;
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_LEFT_FOOT, // 0 => foot
|
|
&foot_x,
|
|
&foot_y,
|
|
&foot_z);
|
|
|
|
foot_x += p_person->WorldPos.X >> 8;
|
|
foot_y += p_person->WorldPos.Y >> 8;
|
|
foot_z += p_person->WorldPos.Z >> 8;
|
|
|
|
SLONG ground = PAP_calc_map_height_at(foot_x, foot_z);
|
|
|
|
if(foot_y>ground+32)
|
|
return(0);
|
|
else
|
|
return(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
SLONG is_person_dead(Thing *p_person)
|
|
{
|
|
if(p_person->State==STATE_DEAD || (p_person->State==STATE_DYING && (p_person->Genus.Person->Flags&FLAG_PERSON_KO)==0))
|
|
return(1);
|
|
else
|
|
return(0);
|
|
|
|
}
|
|
|
|
SLONG is_person_ko(Thing *p_person)
|
|
{
|
|
if (p_person->State == STATE_DYING)
|
|
{
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_DYING_KNOCK_DOWN_WAIT:
|
|
case SUB_STATE_DYING_KNOCK_DOWN: // An extra substate compared to the old version...
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
SLONG is_person_ko_and_lay_down(Thing *p_person)
|
|
{
|
|
if (p_person->State == STATE_DYING)
|
|
{
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_DYING_KNOCK_DOWN_WAIT:
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void knock_person_down(
|
|
Thing *p_person,
|
|
SLONG hitpoints,
|
|
SLONG origin_x,
|
|
SLONG origin_z,
|
|
Thing *p_aggressor)
|
|
{
|
|
SLONG death_type;
|
|
SLONG behind;
|
|
|
|
//
|
|
// Ignore other agreossors... the Balrog for instance!
|
|
//
|
|
|
|
if (p_aggressor && p_aggressor->Class != CLASS_PERSON)
|
|
{
|
|
p_aggressor = NULL;
|
|
}
|
|
|
|
if (p_person->Genus.Person->Flags2 & FLAG2_PERSON_CARRYING)
|
|
{
|
|
//
|
|
// being knocked down better drop who we are carrying
|
|
//
|
|
emergency_uncarry(p_person);
|
|
}
|
|
|
|
|
|
//
|
|
// Look at what caused you to fall over.
|
|
//
|
|
|
|
set_face_pos(
|
|
p_person,
|
|
origin_x,
|
|
origin_z);
|
|
|
|
behind = FALSE;
|
|
|
|
if ((p_person->Genus.Person->pcom_bent & PCOM_BENT_PLAYERKILL) && (!p_aggressor || !p_aggressor->Genus.Person->PlayerID))
|
|
{
|
|
//
|
|
// Only the player can hurt this person...
|
|
//
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->Flags2 & FLAG2_PERSON_INVULNERABLE)
|
|
{
|
|
//
|
|
// Nothing hurts this person.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Hurt the person.
|
|
//
|
|
|
|
p_person->Genus.Person->Health -= hitpoints;
|
|
#ifdef PSX
|
|
if (p_person->Genus.Person->PlayerID)
|
|
PSX_SetShock(1,hitpoints+56);
|
|
#endif
|
|
#ifdef TARGET_DC
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
Vibrate ( 4.0f, (float)( hitpoints+56 ) * 0.003f, 0.25f );
|
|
}
|
|
#endif
|
|
// add_damage_value_thing(p_person,hitpoints>>1);
|
|
}
|
|
|
|
if (p_person->Genus.Person->Health <= 0)
|
|
{
|
|
p_person->Genus.Person->Health = 0;
|
|
death_type = PERSON_DEATH_TYPE_OTHER;
|
|
|
|
if (p_aggressor)
|
|
{
|
|
p_aggressor->Genus.Person->Flags2 |= FLAG2_PERSON_IS_MURDERER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
death_type = PERSON_DEATH_TYPE_STAY_ALIVE;
|
|
}
|
|
|
|
//
|
|
// Knock the person to the floor.
|
|
//
|
|
if (!is_there_room_behind_person(p_person, behind))
|
|
{
|
|
behind = !behind;
|
|
}
|
|
|
|
set_person_dead(
|
|
p_person,
|
|
p_aggressor,
|
|
death_type,
|
|
behind,
|
|
0);
|
|
}
|
|
|
|
|
|
void person_bodge_forward(Thing *p_person,SLONG dist)
|
|
{
|
|
SLONG dx,dy=0,dz;
|
|
GameCoord new_position = p_person->WorldPos;
|
|
|
|
dx =- (SIN(p_person->Draw.Tweened->Angle)*dist)>>8;
|
|
dz =- (COS(p_person->Draw.Tweened->Angle)*dist)>>8;
|
|
|
|
new_position.X += dx;
|
|
new_position.Z += dz;
|
|
|
|
move_thing_on_map(p_person, &new_position);
|
|
|
|
}
|
|
/*
|
|
#define ON_MAP(x,z) ( ((x)>0) && ((x)<MAP_WIDTH) && ((z)>0) && ((z)<MAP_DEPTH) )
|
|
|
|
SLONG find_an_enemy_within_dist(SLONG x,SLONG y,SLONG z,SLONG dist,SLONG group)
|
|
{
|
|
SLONG dx,dz,blocks;
|
|
SLONG mx,mz;
|
|
SLONG index;
|
|
|
|
blocks=dist>>ELE_SHIFT;
|
|
|
|
mx=x>>ELE_SHIFT;
|
|
mz=z>>ELE_SHIFT;
|
|
|
|
for(dx=-blocks;dx<blocks;dx++)
|
|
for(dz=-blocks;dz<blocks;dz++)
|
|
{
|
|
|
|
if(ON_MAP(mx+dx,mz+dz))
|
|
{
|
|
index=MAP2(mx+dx,mz+dz).MapWho;
|
|
while(index)
|
|
{
|
|
Thing *p_thing;
|
|
p_thing=TO_THING(index);
|
|
|
|
switch(p_thing->Class)
|
|
{
|
|
case CLASS_PERSON:
|
|
|
|
break;
|
|
}
|
|
|
|
index=p_thing->Child;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
//
|
|
// Returns TRUE if there is a LOS between the two people's heads.
|
|
//
|
|
|
|
SLONG los_between_heads(
|
|
Thing *person_1,
|
|
Thing *person_2)
|
|
{
|
|
SLONG x1 = person_1->WorldPos.X >> 8;
|
|
SLONG y1 = person_1->WorldPos.Y >> 8;
|
|
SLONG z1 = person_1->WorldPos.Z >> 8;
|
|
|
|
SLONG x2 = person_2->WorldPos.X >> 8;
|
|
SLONG y2 = person_2->WorldPos.Y >> 8;
|
|
SLONG z2 = person_2->WorldPos.Z >> 8;
|
|
|
|
y1 += 0x70;
|
|
y2 += 0x70;
|
|
|
|
return there_is_a_los(
|
|
x1, y1, z1,
|
|
x2, y2, z2,
|
|
0);
|
|
}
|
|
|
|
|
|
//
|
|
// for stack reasons, should make barrel use same memory array
|
|
//
|
|
|
|
extern THING_INDEX col_with[];
|
|
|
|
#ifndef PSX
|
|
void oscilate_tinpanum(SLONG x,SLONG y,SLONG z,Thing *p_thing,SLONG vol)
|
|
{
|
|
SLONG col_with_upto;
|
|
SLONG collide_types = (1 << CLASS_PERSON);
|
|
Thing *col_thing;
|
|
SLONG i;
|
|
|
|
col_with_upto = THING_find_sphere(
|
|
x,
|
|
y,
|
|
z,
|
|
5*256,
|
|
col_with,
|
|
MAX_COL_WITH,
|
|
collide_types);
|
|
|
|
for (i = 0; i < col_with_upto; i++)
|
|
{
|
|
col_thing = TO_THING(col_with[i]);
|
|
|
|
if (col_thing->State == STATE_DEAD ||
|
|
col_thing->State == STATE_DYING)
|
|
{
|
|
//
|
|
// Dead or dying things are of no interest
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
switch(col_thing->Class)
|
|
{
|
|
case CLASS_PERSON:
|
|
|
|
if (col_thing == p_thing)
|
|
{
|
|
//
|
|
// Don't influence yourself!
|
|
//
|
|
}
|
|
else
|
|
{
|
|
if ((col_thing->Genus.Person->Target != THING_NUMBER(p_thing)) &&
|
|
(col_thing->Genus.Person->PlayerID == 0))
|
|
{
|
|
//
|
|
// This person doesn't have me as his target and he is not another player.
|
|
//
|
|
|
|
if (col_thing->State == STATE_IDLE)
|
|
{
|
|
//
|
|
// People only listen while they're doing nothing.
|
|
//
|
|
|
|
if (los_between_heads(col_thing, p_thing))
|
|
{
|
|
set_face_thing(col_thing, p_thing);
|
|
}
|
|
else
|
|
{
|
|
turn_to_face_thing(col_thing,p_thing,2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
SLONG dist_to_target(Thing *p_person_a,Thing *p_person_b)
|
|
{
|
|
SLONG dx,dz;
|
|
|
|
dx=abs(p_person_a->WorldPos.X-p_person_b->WorldPos.X)>>8;
|
|
dz=abs(p_person_a->WorldPos.Z-p_person_b->WorldPos.Z)>>8;
|
|
return(QDIST2(dx,dz));
|
|
}
|
|
|
|
SLONG dist_to_target_pelvis(Thing *p_person_a,Thing *p_person_b)
|
|
{
|
|
SLONG dx,dz;
|
|
SLONG ax,ay,az;
|
|
SLONG bx,by,bz;
|
|
|
|
calc_sub_objects_position(p_person_a,p_person_a->Draw.Tweened->AnimTween,SUB_OBJECT_PELVIS,&ax,&ay,&az);
|
|
calc_sub_objects_position(p_person_b,p_person_b->Draw.Tweened->AnimTween,SUB_OBJECT_PELVIS,&bx,&by,&bz);
|
|
|
|
|
|
dx=(p_person_a->WorldPos.X-p_person_b->WorldPos.X)>>8;
|
|
dz=(p_person_a->WorldPos.Z-p_person_b->WorldPos.Z)>>8;
|
|
|
|
dx+=ax-bx;
|
|
dz+=az-bz;
|
|
|
|
dx=abs(dx);
|
|
dz=abs(dz);
|
|
|
|
return(QDIST2(dx,dz));
|
|
}
|
|
|
|
//
|
|
// Returns TRUE if a person is crouching
|
|
//
|
|
|
|
SLONG is_person_crouching(Thing *p_person)
|
|
{
|
|
ASSERT(p_person->Class == CLASS_PERSON);
|
|
|
|
return
|
|
p_person->SubState == SUB_STATE_CRAWLING ||
|
|
p_person->SubState == SUB_STATE_STOP_CRAWL ||
|
|
p_person->SubState == SUB_STATE_IDLE_CROUTCH ||
|
|
p_person->SubState == SUB_STATE_IDLE_CROUTCHING;
|
|
}
|
|
|
|
|
|
//
|
|
// Returns TRUE if person_a can see person_b
|
|
//
|
|
|
|
//
|
|
// range is a theoretical maximum range of sight for person_a default==0
|
|
// ==0 use default range 8<<8
|
|
// <0 means forget view conditions and just use max range (useful for player)
|
|
// >0 clip calculated view distance to this value
|
|
|
|
SLONG can_a_see_b(
|
|
Thing *p_person_a,
|
|
Thing *p_person_b,SLONG range,SLONG no_los)
|
|
{
|
|
SLONG dx;
|
|
SLONG dy;
|
|
SLONG dz;
|
|
|
|
SLONG view;
|
|
SLONG dist;
|
|
SLONG angle;
|
|
SLONG dangle;
|
|
SLONG p_person_b_moving;
|
|
|
|
|
|
if(p_person_a->Flags&FLAGS_PERSON_BEEN_SHOT)
|
|
{
|
|
range=-(9<<8);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
// Makes people go berserk! I'm gonna stop them shooting/punching/kicking instead.
|
|
|
|
if(p_person_b->Class==CLASS_PERSON && p_person_b->Genus.Person->PlayerID && EWAY_stop_player_moving())
|
|
{
|
|
//
|
|
// can't see player during cut scene
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
*/
|
|
|
|
if (p_person_a->Genus.Person->Ware !=
|
|
p_person_b->Genus.Person->Ware)
|
|
{
|
|
//
|
|
// These two people are in different warehouses or one is in a warehouse
|
|
// while the other isn't.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if(range==0)
|
|
{
|
|
range=8<<8;
|
|
}
|
|
|
|
//
|
|
// Is darci moving?
|
|
//
|
|
|
|
p_person_b_moving = TRUE;
|
|
|
|
if (p_person_b->State == STATE_IDLE || (p_person_b->State == STATE_GUN && p_person_b->SubState == SUB_STATE_AIM_GUN))
|
|
{
|
|
p_person_b_moving = FALSE;
|
|
}
|
|
|
|
dx = p_person_b->WorldPos.X - p_person_a->WorldPos.X;
|
|
dy = p_person_b->WorldPos.Y - p_person_a->WorldPos.Y;
|
|
dz = p_person_b->WorldPos.Z - p_person_a->WorldPos.Z;
|
|
|
|
dx >>= 8;
|
|
dy >>= 8;
|
|
dz >>= 8;
|
|
|
|
dist = QDIST2(abs(dx),abs(dz));
|
|
|
|
//
|
|
// How far a can see b from depends on the amount of light falling on b.
|
|
//
|
|
|
|
if(range<0)
|
|
{
|
|
//
|
|
// -ve range so ignore view conditions
|
|
//
|
|
view=-range;
|
|
}
|
|
else
|
|
{
|
|
if (p_person_a->Genus.Person->PlayerID)
|
|
{
|
|
view = 256 << 8;
|
|
}
|
|
else
|
|
{
|
|
NIGHT_Colour col;
|
|
|
|
col = NIGHT_get_light_at(
|
|
p_person_b->WorldPos.X >> 8,
|
|
p_person_b->WorldPos.Y >> 8,
|
|
p_person_b->WorldPos.Z >> 8);
|
|
|
|
//
|
|
// See further in good light.
|
|
//
|
|
|
|
view = col.red + col.green + col.blue;
|
|
view += view << 3;
|
|
view += view >> 2;
|
|
view += 256;
|
|
}
|
|
|
|
if (is_person_crouching(p_person_b))
|
|
{
|
|
view >>= 1;
|
|
}
|
|
|
|
if (p_person_b_moving)
|
|
{
|
|
view += 256;
|
|
}
|
|
|
|
if (view > range) //256 * 8)
|
|
{
|
|
view = range; //256 * 8;
|
|
}
|
|
}
|
|
|
|
|
|
if (dist > view) // this should be an #define or a table lookup for people types
|
|
{
|
|
//
|
|
// Too far away.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
{
|
|
//
|
|
// Distance and dy is ok.
|
|
//
|
|
|
|
angle = Arctan(dx,-dz) + 1024;
|
|
angle &= 2047;
|
|
dangle = angle - p_person_a->Draw.Tweened->Angle;
|
|
dangle &= 2047;
|
|
|
|
if (dist < 0xc0)
|
|
{
|
|
//
|
|
// Very large field of view at this low range!
|
|
//
|
|
|
|
if (dangle < 700 || dangle > 2048 - 700)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#define PEOPLE_FOV 420 //was 320
|
|
|
|
if (dangle < PEOPLE_FOV || dangle > 2048 - PEOPLE_FOV)
|
|
{
|
|
//
|
|
// Seeing someone out of the corner of your eye reduces your
|
|
// viewing distance... if they are not moving.
|
|
//
|
|
|
|
if (!p_person_b_moving)
|
|
{
|
|
#define CORNER_OF_EYE_FOV 250
|
|
|
|
if (WITHIN(dangle, CORNER_OF_EYE_FOV, 2048 - CORNER_OF_EYE_FOV))
|
|
{
|
|
if (dist > (view >> 1))
|
|
{
|
|
//
|
|
// Too far away to see out of the corner of your eye.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// The height of each person's head.
|
|
//
|
|
|
|
UBYTE ahead = (is_person_crouching(p_person_a)) ? 0x20 : 0x60;
|
|
UBYTE bhead = (is_person_crouching(p_person_b)) ? 0x20 : 0x60;
|
|
|
|
//
|
|
// Angle is valid
|
|
//
|
|
|
|
if(no_los)
|
|
return(TRUE);
|
|
|
|
if (p_person_b->Genus.Person->Ware)
|
|
{
|
|
//
|
|
// there_is_a_los() works as long as you don't do the underground check.
|
|
//
|
|
|
|
if (there_is_a_los(
|
|
(p_person_a->WorldPos.X >> 8),
|
|
(p_person_a->WorldPos.Y >> 8) + ahead,
|
|
(p_person_a->WorldPos.Z >> 8),
|
|
(p_person_b->WorldPos.X >> 8),
|
|
(p_person_b->WorldPos.Y >> 8) + bhead,
|
|
(p_person_b->WorldPos.Z >> 8),
|
|
LOS_FLAG_IGNORE_UNDERGROUND_CHECK))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (there_is_a_los(
|
|
(p_person_a->WorldPos.X >> 8),
|
|
(p_person_a->WorldPos.Y >> 8) + ahead,
|
|
(p_person_a->WorldPos.Z >> 8),
|
|
(p_person_b->WorldPos.X >> 8),
|
|
(p_person_b->WorldPos.Y >> 8) + bhead,
|
|
(p_person_b->WorldPos.Z >> 8),
|
|
0))
|
|
{
|
|
//
|
|
// No building in the way
|
|
//
|
|
|
|
/*
|
|
|
|
AENG_world_line(
|
|
(p_person_a->WorldPos.X >> 8),
|
|
(p_person_a->WorldPos.Y >> 8) + 0x60,
|
|
(p_person_a->WorldPos.Z >> 8),
|
|
32,
|
|
0x00ffffff,
|
|
(p_person_b->WorldPos.X >> 8),
|
|
(p_person_b->WorldPos.Y >> 8) + 0x60,
|
|
(p_person_b->WorldPos.Z >> 8),
|
|
0,
|
|
0x00123456,
|
|
TRUE);
|
|
|
|
*/
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
SLONG can_i_see_place(Thing *p_person, SLONG x, SLONG y, SLONG z)
|
|
{
|
|
SLONG dx;
|
|
SLONG dy;
|
|
SLONG dz;
|
|
|
|
SLONG view;
|
|
SLONG dist;
|
|
SLONG angle;
|
|
SLONG dangle;
|
|
|
|
dx = x - (p_person->WorldPos.X >> 8);
|
|
dy = y - (p_person->WorldPos.Y >> 8);
|
|
dz = z - (p_person->WorldPos.Z >> 8);
|
|
|
|
dist = QDIST2(abs(dx),abs(dz));
|
|
|
|
if (dist > 0x600)
|
|
{
|
|
//
|
|
// Too far away.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (abs(dy) > abs(dist >> 1))
|
|
{
|
|
//
|
|
// Too high up.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Distance and dy is ok.
|
|
//
|
|
|
|
angle = Arctan(dx,-dz) + 1024;
|
|
angle &= 2047;
|
|
dangle = angle - p_person->Draw.Tweened->Angle;
|
|
dangle &= 2047;
|
|
|
|
#define PEOPLE_FOV 420 //was 320
|
|
|
|
if (dangle < PEOPLE_FOV || dangle > 2048 - PEOPLE_FOV)
|
|
{
|
|
//
|
|
// The height of each person's head.
|
|
//
|
|
|
|
UBYTE ahead = (is_person_crouching(p_person)) ? 0x20 : 0x60;
|
|
|
|
//
|
|
// Angle is valid
|
|
//
|
|
|
|
if (there_is_a_los(
|
|
(p_person->WorldPos.X >> 8),
|
|
(p_person->WorldPos.Y >> 8) + ahead,
|
|
(p_person->WorldPos.Z >> 8),
|
|
x,
|
|
y + 0x20, // So we can see things on the ground.
|
|
z,
|
|
0))
|
|
{
|
|
//
|
|
// No building in the way
|
|
//
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void set_person_sliding_tackle(Thing *p_person, Thing *p_target)
|
|
{
|
|
if(p_person->SubState!=SUB_STATE_RUNNING_SKID_STOP)
|
|
{
|
|
set_face_thing(p_person, p_target);
|
|
set_generic_person_state_function(p_person, STATE_MOVEING);
|
|
set_anim(p_person, ANIM_SLIDER_START);
|
|
p_person->SubState = SUB_STATE_RUNNING_SKID_STOP;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Returns TRUE if the person vaults...
|
|
//
|
|
|
|
SLONG set_person_vault(Thing *p_person, SLONG facet)
|
|
{
|
|
if(set_person_pos_for_fence_vault(p_person,facet))
|
|
{
|
|
set_anim(p_person,ANIM_VAULT);
|
|
p_person->SubState = SUB_STATE_RUNNING_VAULT;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C;
|
|
|
|
set_generic_person_state_function(p_person, STATE_MOVEING);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
SLONG set_person_climb_half(Thing *p_person, SLONG facet)
|
|
{
|
|
if(set_person_pos_for_half_step(p_person,facet))
|
|
{
|
|
set_anim(p_person,ANIM_GET_UP_HALF_BLOCK);
|
|
p_person->SubState = SUB_STATE_RUNNING_HALF_BLOCK;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C;
|
|
|
|
set_generic_person_state_function(p_person, STATE_MOVEING);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// can person see player
|
|
//
|
|
|
|
SLONG can_i_see_player(Thing *p_person)
|
|
{
|
|
//
|
|
// THERE MIGHT BE TWO PLAYERS NOW REMEMBER!
|
|
//
|
|
|
|
|
|
return can_a_see_b(p_person, NET_PERSON(0));
|
|
}
|
|
|
|
void do_look_for_enemies(Thing *p_person)
|
|
{
|
|
//
|
|
// THERE MIGHT BE TWO PLAYERS NOW REMEMBER!
|
|
//
|
|
|
|
|
|
//
|
|
// for now the player is the only enemy
|
|
//
|
|
|
|
if (can_i_see_player(p_person))
|
|
{
|
|
//
|
|
// Navigate to the player.
|
|
//
|
|
|
|
p_person->Genus.Person->Target = THING_NUMBER(NET_PERSON(0));
|
|
ASSERT(p_person->Genus.Person->Target != THING_NUMBER(p_person));
|
|
ASSERT(TO_THING(p_person->Genus.Person->Target)->Class==CLASS_PERSON);
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NAV_TO_KILL;
|
|
|
|
set_person_mav_to_thing(p_person,NET_PERSON(0));
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the person is too far from home or Darci sets of home again.
|
|
//
|
|
#ifdef UNUSED
|
|
void show_me_the_way_to_go_home(Thing *p_person)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
|
|
SLONG home_x = p_person->Genus.Person->HomeX << 8;
|
|
SLONG home_z = p_person->Genus.Person->HomeZ << 8;
|
|
|
|
SLONG home_sickness;
|
|
SLONG darci_distance;
|
|
|
|
//
|
|
// Far from home?
|
|
//
|
|
|
|
dx = home_x - p_person->WorldPos.X;
|
|
dz = home_z - p_person->WorldPos.Z;
|
|
|
|
home_sickness = abs(dx) + abs(dz); // i.e. Distance from home!
|
|
|
|
//
|
|
// Far from Darci?
|
|
//
|
|
|
|
dx = NET_PERSON(0)->WorldPos.X - p_person->WorldPos.X;
|
|
dz = NET_PERSON(0)->WorldPos.Z - p_person->WorldPos.Z;
|
|
|
|
darci_distance = abs(dx) + abs(dz);
|
|
|
|
//
|
|
// Go home?
|
|
//
|
|
|
|
if (home_sickness > 0x100000 || (home_sickness > 0x018000 && darci_distance > 0x80000))
|
|
{
|
|
p_person->Genus.Person->Target = NULL;
|
|
|
|
set_person_mav_to_xz(
|
|
p_person,
|
|
home_x >> 8,
|
|
home_z >> 8);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
extern void play_music(UWORD id, UBYTE track);
|
|
|
|
|
|
ULONG timer_bored=0;
|
|
void general_process_player(Thing *p_person)
|
|
{
|
|
DrawTween *dt;
|
|
|
|
if (p_person->Genus.Person->Mode == PERSON_MODE_FIGHT)
|
|
{
|
|
if (p_person->State == STATE_MOVEING &&
|
|
p_person->SubState == SUB_STATE_RUNNING)
|
|
{
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
}
|
|
}
|
|
|
|
#if PSX
|
|
|
|
if(player_dlight==0)
|
|
{
|
|
player_dlight = NIGHT_dlight_create( p_person->WorldPos.X>>8, (p_person->WorldPos.Y>>8)+128, p_person->WorldPos.Z>>8, 200, 4, 4, 4);
|
|
|
|
}
|
|
else
|
|
{
|
|
NIGHT_dlight_move(player_dlight,p_person->WorldPos.X>>8, (p_person->WorldPos.Y>>8)+64, p_person->WorldPos.Z>>8);
|
|
}
|
|
|
|
#endif
|
|
|
|
if(p_person->Genus.Person->GangAttack)
|
|
{
|
|
extern void check_players_gang(Thing *p_target);
|
|
check_players_gang(p_person);
|
|
}
|
|
/*
|
|
if(p_person->Genus.Person->Mode==PERSON_MODE_SPRINT)
|
|
{
|
|
AENG_world_line(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
16,
|
|
0xff0000,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0 + 0x1000 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
0,
|
|
0x330088,
|
|
FALSE);
|
|
}
|
|
*/
|
|
|
|
|
|
if(p_person->Genus.Person->Mode==PERSON_MODE_FIGHT)
|
|
{
|
|
|
|
if(p_person->Genus.Person->Target)
|
|
{
|
|
Thing *p_target;
|
|
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
//
|
|
// player has a target, lets see if we should bin it
|
|
//
|
|
|
|
// if((p_target->State==STATE_DEAD) ||(p_target->State==STATE_DYING && (p_target->Genus.Person->Flags&FLAG_PERSON_KO)==0))
|
|
if(is_person_dead(p_target))
|
|
{
|
|
//
|
|
// find a better target
|
|
//
|
|
|
|
fight_any_gang_attacker(p_person);
|
|
|
|
}
|
|
}
|
|
else
|
|
if(count_gang(p_person))
|
|
{
|
|
fight_any_gang_attacker(p_person);
|
|
}
|
|
|
|
timer_bored=0;
|
|
}
|
|
else
|
|
{
|
|
if(!EWAY_stop_player_moving())
|
|
timer_bored+=TICK_TOCK;
|
|
}
|
|
|
|
|
|
dt=p_person->Draw.Tweened;
|
|
if(p_person->SubState==SUB_STATE_RUNNING)
|
|
{
|
|
if(dt->Roll||dt->DRoll)
|
|
{
|
|
//
|
|
// This is a really crap place to put this, but where else can it go?
|
|
//
|
|
|
|
if(dt->DRoll)
|
|
{
|
|
if(abs(dt->Roll)<70)
|
|
dt->Roll-=dt->DRoll;
|
|
|
|
//
|
|
// when you swap direction need to clear roll
|
|
//
|
|
if(dt->Roll>0 && dt->DRoll>0)
|
|
dt->Roll=0;
|
|
else
|
|
if(dt->Roll<0 && dt->DRoll<0)
|
|
dt->Roll=0;
|
|
dt->DRoll=0;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// uses 2's complement maths shift feature
|
|
//
|
|
if(dt->Roll<0)
|
|
dt->Roll-=(dt->Roll>>1);
|
|
if(dt->Roll>0)
|
|
dt->Roll+=(-dt->Roll)>>1;
|
|
|
|
}
|
|
|
|
}
|
|
if(p_person->Genus.Person->Flags2&FLAG2_PERSON_CARRYING)
|
|
{
|
|
TO_THING(p_person->Genus.Person->Target)->Draw.Tweened->Roll=(2048-dt->Roll)&2047;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if(p_person->SubState==SUB_STATE_WALKING)
|
|
{
|
|
/*
|
|
if((GAME_TURN&3)==0)
|
|
{
|
|
if(should_i_sneak(p_person))
|
|
{
|
|
if(p_person->Genus.Person->Mode!=PERSON_MODE_SNEAK)
|
|
{
|
|
p_person->Genus.Person->Mode=PERSON_MODE_SNEAK;
|
|
set_person_sneaking(p_person);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Genus.Person->Mode!=PERSON_MODE_WALK)
|
|
{
|
|
p_person->Genus.Person->Mode=PERSON_MODE_WALK;
|
|
set_person_walking(p_person);
|
|
}
|
|
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
if (p_person->SubState != SUB_STATE_RIDING_BIKE)
|
|
{
|
|
if(dt->Roll<0)
|
|
dt->Roll-=(dt->Roll>>2);
|
|
if(dt->Roll>0)
|
|
dt->Roll+=(-dt->Roll)>>2;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void person_pick_best_target(Thing *p_person,SLONG dir)
|
|
{
|
|
SLONG i;
|
|
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG dist;
|
|
SLONG best_dist = INFINITY;
|
|
|
|
UWORD lowest_person = 0xffff;
|
|
UWORD highest_person = 0;
|
|
UWORD next_person = 0xffff;
|
|
UWORD prev_person = 0;
|
|
|
|
SLONG num_found = THING_find_sphere(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
0x300,
|
|
THING_array,
|
|
THING_ARRAY_SIZE,
|
|
1 << CLASS_PERSON);
|
|
|
|
for (i = 0; i < num_found; i++)
|
|
{
|
|
Thing *p_found = TO_THING(THING_array[i]);
|
|
|
|
if (p_found == p_person)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (p_found->State == STATE_DEAD)
|
|
{
|
|
//
|
|
// Ignore dead and arrested people.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
if (PCOM_person_wants_to_kill(p_found) == THING_NUMBER(p_person))
|
|
{
|
|
if (p_person->Genus.Person->Target == NULL)
|
|
{
|
|
//
|
|
// Pick the nearest person.
|
|
//
|
|
|
|
dx = abs(p_found->WorldPos.X - p_person->WorldPos.X);
|
|
dz = abs(p_found->WorldPos.Z - p_person->WorldPos.Z);
|
|
|
|
dist = QDIST2(dx,dz);
|
|
|
|
if (dist < best_dist)
|
|
{
|
|
best_dist = dist;
|
|
next_person = THING_array[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Found someone who wants to kill me.
|
|
//
|
|
|
|
if (THING_array[i] < lowest_person)
|
|
{
|
|
lowest_person = THING_array[i];
|
|
}
|
|
if (THING_array[i] > highest_person)
|
|
{
|
|
highest_person = THING_array[i];
|
|
}
|
|
|
|
if (THING_array[i] > p_person->Genus.Person->Target)
|
|
{
|
|
if (THING_array[i] < next_person)
|
|
{
|
|
next_person = THING_array[i];
|
|
}
|
|
}
|
|
else
|
|
if (THING_array[i] < p_person->Genus.Person->Target)
|
|
{
|
|
if (THING_array[i] > prev_person)
|
|
{
|
|
prev_person = THING_array[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dir==1)
|
|
{
|
|
if (next_person != 0xffff)
|
|
{
|
|
p_person->Genus.Person->Target = next_person;
|
|
}
|
|
else
|
|
if (lowest_person != 0xffff)
|
|
{
|
|
p_person->Genus.Person->Target = lowest_person;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (prev_person != 0xffff)
|
|
{
|
|
p_person->Genus.Person->Target = prev_person;
|
|
}
|
|
else
|
|
if (highest_person != 0xffff)
|
|
{
|
|
p_person->Genus.Person->Target = highest_person;
|
|
}
|
|
}
|
|
|
|
if (p_person->Genus.Person->Target)
|
|
{
|
|
turn_to_face_thing(p_person,TO_THING(p_person->Genus.Person->Target),0);
|
|
}
|
|
|
|
/*
|
|
|
|
UWORD target;
|
|
extern UWORD get_nearest_gang_member(Thing *p_target);
|
|
target=get_nearest_gang_member(p_person);
|
|
if(target)
|
|
{
|
|
turn_to_face_thing(p_person,TO_THING(target),0);
|
|
p_person->Genus.Person->Target=target;
|
|
}
|
|
|
|
*/
|
|
}
|
|
|
|
|
|
void general_process_person(Thing *p_person)
|
|
{
|
|
/*
|
|
if(p_person->State!=STATE_DEAD && p_person->State!=STATE_DYING)
|
|
{
|
|
if(p_person->Genus.Person->PersonType==PERSON_CIV)
|
|
if(p_person->Genus.Person->PersonType!=PERSON_ROPER)
|
|
if(p_person->Genus.Person->PersonType!=PERSON_HOSTAGE)
|
|
if(p_person->Genus.Person->PlayerID==0)
|
|
if(p_person->Genus.Person->InCar==0)
|
|
{
|
|
if((PTIME(p_person)&63)==0)
|
|
{
|
|
set_person_dead(p_person, NULL, PERSON_DEATH_TYPE_PRONE, 0, 0);
|
|
// set_person_dead(p_person);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/*
|
|
#ifdef PSX
|
|
// ASSERT(p_person->Draw.Tweened!=TO_DRAW_TWEEN(0));
|
|
|
|
if(p_person->State!=STATE_DEAD)
|
|
switch(p_person->Genus.Person->PersonType)
|
|
{
|
|
case PERSON_CIV:
|
|
ASSERT(p_person->Draw.Tweened->MeshID>6 &&p_person->Draw.Tweened->MeshID<10);
|
|
break;
|
|
}
|
|
#endif
|
|
*/
|
|
|
|
/*
|
|
if(p_person->Genus.Person->InCar)
|
|
AENG_world_line(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
16,
|
|
0xff0000,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0 + 0x21000 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
0,
|
|
0x330088,
|
|
FALSE);
|
|
*/
|
|
//
|
|
// every 64 turns clear the flag been shot, this flag gives you super vision
|
|
//
|
|
// if((GAME_TURN&63)==(THING_NUMBER(p_person)&63))
|
|
if((PTIME(p_person)&63)==0)
|
|
{
|
|
p_person->Flags&=~FLAGS_PERSON_BEEN_SHOT;
|
|
}
|
|
|
|
// if(Keys[KB_F])
|
|
// p_person->WorldPos.Y=0;
|
|
|
|
|
|
#ifndef NDEBUG
|
|
// if(p_person->Genus.Person->Flags2&FLAG2_PERSON_GUILTY)
|
|
/*
|
|
if(p_person->Genus.Person->OnFacet)
|
|
{
|
|
AENG_world_line(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
16,
|
|
0xff0000,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0 + 0x21000 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
0,
|
|
0x330088,
|
|
FALSE);
|
|
}
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_FELON)
|
|
{
|
|
AENG_world_line(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
16,
|
|
0x00ffff,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0 + 0x21000 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
0,
|
|
0x33ff88,
|
|
FALSE);
|
|
}
|
|
*/
|
|
if(ControlFlag)
|
|
if(p_person->Genus.Person->Target)
|
|
{
|
|
Thing *p_target;
|
|
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
AENG_world_line(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0x1000 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
16,
|
|
0x00ffff,
|
|
p_target->WorldPos.X >> 8,
|
|
p_target->WorldPos.Y + 0 + 0x1000 >> 8,
|
|
p_target->WorldPos.Z >> 8,
|
|
0,
|
|
0x33ff88,
|
|
FALSE);
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
if (p_person->OnFace && p_person->OnFace < 0 && p_person->State != STATE_DEAD)
|
|
{
|
|
if (IS_ROOF_HIDDEN_FACE(p_person->OnFace))
|
|
{
|
|
SLONG mx = ROOF_HIDDEN_X(p_person->OnFace);
|
|
SLONG mz = ROOF_HIDDEN_Z(p_person->OnFace);
|
|
|
|
ASSERT(abs(mx - (p_person->WorldPos.X >> 16)) <= 1);
|
|
ASSERT(abs(mz - (p_person->WorldPos.Z >> 16)) <= 1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifndef PSX
|
|
/*
|
|
if(p_person->Genus.Person->PlayerID==0)
|
|
{
|
|
if(!is_person_dead(p_person))
|
|
if(can_a_see_b(p_person,NET_PERSON(0)))
|
|
{
|
|
Thing *p_target=NET_PERSON(0);
|
|
AENG_world_line_infinite(p_target->WorldPos.X>>8,p_target->WorldPos.Y>>8,p_target->WorldPos.Z>>8,1,0x00ff00,p_person->WorldPos.X>>8,p_person->WorldPos.Y>>8,p_person->WorldPos.Z>>8,5,0x00ff00,1);
|
|
}
|
|
}
|
|
*/
|
|
#endif
|
|
/*
|
|
if (p_person->Genus.Person->Flags2 & FLAG2_PERSON_FAKE_WANDER)
|
|
{
|
|
DebugText(" %d %d %d \n",p_person->State,p_person->SubState,p_person->Genus.Person->pcom_ai);
|
|
}
|
|
*/
|
|
// p_person->Genus.Person->Flags &=~ FLAG_PERSON_DID_ANIMATE;
|
|
/*
|
|
if(p_person->Draw.Tweened->CurrentFrame==p_person->Draw.Tweened->NextFrame)
|
|
{
|
|
AENG_world_line(p_person->WorldPos.X >> 8,p_person->WorldPos.Y + 0x0000 >> 8,p_person->WorldPos.Z >> 8,
|
|
32,0x00ff00,p_person->WorldPos.X >> 8,p_person->WorldPos.Y + 0x1000 >> 8,p_person->WorldPos.Z >> 8,
|
|
0,
|
|
0x000000,
|
|
TRUE);
|
|
}
|
|
*/
|
|
#ifndef NDEBUG
|
|
/*
|
|
{
|
|
Thing *p_target;
|
|
|
|
if (WITHIN(p_person->Genus.Person->Target, 1, MAX_THINGS - 1))
|
|
{
|
|
p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
if (p_target->Class == CLASS_PERSON)
|
|
{
|
|
AENG_world_line(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0x1000 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
32,
|
|
0xff0000,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0x1000 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
0,
|
|
0x000000,
|
|
TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Draw an arrow over helpless people!
|
|
//
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_HELPLESS)
|
|
{
|
|
SLONG px;
|
|
SLONG py;
|
|
SLONG pz;
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_HEAD,
|
|
&px,
|
|
&py,
|
|
&pz);
|
|
|
|
px += p_person->WorldPos.X >> 8;
|
|
py += p_person->WorldPos.Y >> 8;
|
|
pz += p_person->WorldPos.Z >> 8;
|
|
|
|
AENG_world_line(
|
|
px, py, pz, 0, 0xffffff,
|
|
px, py + 20, pz, 32, 0xccccff,
|
|
FALSE);
|
|
}
|
|
*/
|
|
|
|
#endif
|
|
|
|
// ASSERT(p_person->WorldPos.X>>16<128);
|
|
// ASSERT(p_person->WorldPos.Z>>16<128);
|
|
|
|
|
|
if (p_person->OnFace>0)
|
|
{
|
|
ASSERT(WITHIN(p_person->OnFace, 1, next_prim_face4 - 1));
|
|
|
|
PrimFace4 *f4 = &prim_faces4[p_person->OnFace];
|
|
|
|
ASSERT(f4->FaceFlags & FACE_FLAG_WALKABLE);
|
|
|
|
if (f4->FaceFlags & FACE_FLAG_WMOVE)
|
|
{
|
|
SLONG now_x;
|
|
SLONG now_y;
|
|
SLONG now_z;
|
|
SLONG now_dangle;
|
|
SLONG wmove_index;
|
|
|
|
wmove_index=f4->ThingIndex;
|
|
ASSERT(WITHIN(wmove_index, 1, WMOVE_face_upto - 1));
|
|
|
|
WMOVE_relative_pos(
|
|
f4->ThingIndex,
|
|
p_person->WorldPos.X,
|
|
p_person->WorldPos.Y,
|
|
p_person->WorldPos.Z,
|
|
&now_x,
|
|
&now_y,
|
|
&now_z,
|
|
&now_dangle);
|
|
|
|
p_person->Draw.Tweened->Angle += now_dangle;
|
|
p_person->Draw.Tweened->Angle &= 2047;
|
|
|
|
//
|
|
// Make sure you don't end up too near the edge of the map!
|
|
//
|
|
|
|
GameCoord newpos;
|
|
|
|
newpos.X = now_x;
|
|
newpos.Y = now_y;
|
|
newpos.Z = now_z;
|
|
|
|
if (WITHIN(newpos.X, 2 << 16, (PAP_SIZE_HI - 3) << 16) &&
|
|
WITHIN(newpos.Z, 2 << 16, (PAP_SIZE_HI - 3) << 16))
|
|
{
|
|
|
|
move_thing_on_map(p_person, &newpos);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Too close to the edge of the map! Fall off.
|
|
//
|
|
|
|
p_person->OnFace = 0;
|
|
|
|
set_person_dead(
|
|
p_person,
|
|
NULL,
|
|
PERSON_DEATH_TYPE_STAY_ALIVE,
|
|
0,
|
|
0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (p_person->State == STATE_DEAD ||
|
|
p_person->State == STATE_DYING)
|
|
{
|
|
//
|
|
// Dead or dying things are of no interest
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
if (GAME_FLAGS & GF_NO_FLOOR)
|
|
{
|
|
if (p_person->WorldPos.Y < -0x180000)
|
|
{
|
|
//
|
|
// This person is dead!
|
|
//
|
|
|
|
p_person->Genus.Person->Health = 0;
|
|
|
|
set_person_dead(p_person, NULL, PERSON_DEATH_TYPE_PRONE, 0, 0);
|
|
|
|
remove_thing_from_map(p_person);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
{
|
|
UWORD max_stamina=128;
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
max_stamina+=NET_PLAYER(p_person->Genus.Person->PlayerID-1)->Genus.Player->Stamina;
|
|
if(!continue_pressing_action(p_person))
|
|
{
|
|
if (p_person->Genus.Person->Stamina < max_stamina)
|
|
{
|
|
p_person->Genus.Person->Stamina++;
|
|
|
|
if (p_person->Genus.Person->Stamina == 5)
|
|
{
|
|
p_person->Genus.Person->Stamina = 20;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->Stamina < max_stamina)
|
|
{
|
|
p_person->Genus.Person->Stamina++;
|
|
}
|
|
}
|
|
|
|
// check for burning flags
|
|
|
|
SLONG get_person_radius(SLONG type);
|
|
|
|
if (p_person->Flags & FLAGS_BURNING) {
|
|
SLONG x2,y2,z2,ndx;
|
|
Thing *thing;
|
|
Pyro *pyro;
|
|
TRACE("the pain the pain\n");
|
|
|
|
ndx=p_person->Genus.Person->BurnIndex;
|
|
if ((!ndx)||((pyro=TO_PYRO(ndx-1))->PyroType==PYRO_NONE)) {
|
|
thing=PYRO_create(p_person->WorldPos,PYRO_IMMOLATE);
|
|
if (thing)
|
|
{
|
|
pyro=thing->Genus.Pyro;
|
|
pyro->victim=p_person;
|
|
pyro->Flags=PYRO_FLAGS_FLICKER; // immolate faces
|
|
p_person->Genus.Person->BurnIndex=PYRO_NUMBER(pyro)+1;
|
|
thing->StateFn(thing);
|
|
}
|
|
} else {
|
|
// add to it's life theoretically... unless in water
|
|
if (PAP_2HI(p_person->WorldPos.X>>16,p_person->WorldPos.Z>>16).Flags & PAP_FLAG_WATER) {
|
|
if (pyro->PyroType==PYRO_IMMOLATE) {
|
|
pyro->Dummy=2;
|
|
pyro->radius=290;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_person->Genus.Person->pcom_bent & PCOM_BENT_PLAYERKILL)
|
|
{
|
|
//
|
|
// Only the player can hurt this person.
|
|
//
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->Flags2 & FLAG2_PERSON_INVULNERABLE)
|
|
{
|
|
//
|
|
// Nothing hurts this person.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Health-=30;
|
|
// add_damage_value_thing(p_person,30>>1);
|
|
}
|
|
|
|
if(p_person->Genus.Person->Health<=0)
|
|
{
|
|
p_person->Genus.Person->Health=0;
|
|
|
|
set_person_dead(
|
|
p_person,
|
|
NULL,
|
|
PERSON_DEATH_TYPE_OTHER,
|
|
FALSE,
|
|
0);
|
|
|
|
} else {
|
|
|
|
// later it'd be nice to only turn this off after a delay
|
|
p_person->Flags &= ~FLAGS_BURNING;
|
|
collide_against_things(
|
|
p_person,
|
|
get_person_radius(p_person->Genus.Person->PersonType),
|
|
p_person->WorldPos.X,p_person->WorldPos.Y,p_person->WorldPos.Z,
|
|
&x2,&y2,&z2);
|
|
|
|
if (!(p_person->Flags & FLAGS_BURNING))
|
|
TRACE("oh that's much better thankyou\n");
|
|
}
|
|
}
|
|
|
|
// used to have something somewhere else to do this, but it appears to have vanished.
|
|
// so here's something to do it. :P
|
|
|
|
if (p_person->Genus.Person->BurnIndex && (p_person->Genus.Person->Health>0))
|
|
p_person->Genus.Person->Health--;
|
|
|
|
|
|
//
|
|
// If urinating... then pee!
|
|
//
|
|
|
|
#ifndef PSX // save Eidos/Sony the trouble of instructing us to remove this
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_PEEING)
|
|
{
|
|
if (p_person->Flags & FLAGS_IN_VIEW)
|
|
{
|
|
SLONG penis_x;
|
|
SLONG penis_y;
|
|
SLONG penis_z;
|
|
|
|
SLONG dx;
|
|
SLONG dz;
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_PELVIS,
|
|
&penis_x,
|
|
&penis_y,
|
|
&penis_z);
|
|
|
|
penis_x += p_person->WorldPos.X >> 8;
|
|
penis_y += p_person->WorldPos.Y >> 8;
|
|
penis_z += p_person->WorldPos.Z >> 8;
|
|
|
|
penis_y -= 0x10;
|
|
|
|
dx = -SIN(p_person->Draw.Tweened->Angle) >> 13;
|
|
dz = -COS(p_person->Draw.Tweened->Angle) >> 13;
|
|
|
|
DIRT_new_water(
|
|
penis_x,
|
|
penis_y,
|
|
penis_z,
|
|
dx, -2, dz,
|
|
DIRT_TYPE_URINE);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// if dying, leave blood trails
|
|
if (p_person->Genus.Person->Health<health[p_person->Genus.Person->PersonType]>>2)
|
|
{
|
|
if(p_person->Genus.Person->Stamina>50)
|
|
p_person->Genus.Person->Stamina-=1; //bleeding people lose stamina all the time
|
|
|
|
if (!p_person->Genus.Person->InCar)
|
|
{
|
|
if (((Random()&0x7f)>p_person->Genus.Person->Health)&&(Random()&1)) TRACKS_Bleed(p_person);
|
|
}
|
|
}
|
|
|
|
|
|
#if DARCI_HITS_COPS
|
|
|
|
if (p_person->Genus.Person->UnderAttack)
|
|
{
|
|
SLONG ticks = 256 * TICK_RATIO >> TICK_SHIFT;
|
|
|
|
if (p_person->Genus.Person->UnderAttack <= ticks)
|
|
{
|
|
p_person->Genus.Person->UnderAttack = 0;
|
|
}
|
|
else
|
|
{
|
|
SLONG last = p_person->Genus.Person->UnderAttack;
|
|
|
|
p_person->Genus.Person->UnderAttack -= ticks;
|
|
|
|
if (last > 0xffff - (256 * 20 * 2) &&
|
|
last - ticks <= 0xffff - (256 * 20 * 2))
|
|
{
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_COP &&
|
|
p_person->Genus.Person->pcom_ai_state == PCOM_AI_STATE_NORMAL)
|
|
{
|
|
PCOM_set_person_ai_talk_to(
|
|
p_person,
|
|
NET_PERSON(0),
|
|
PCOM_AI_SUBSTATE_TALK_ASK,
|
|
FALSE);
|
|
|
|
|
|
// PANEL_new_text(p_person, 4000, "Hey! Why are you hitting me, Darci?");
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Does this person have the grappling hook?
|
|
//
|
|
#ifndef PSX
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GRAPPLING)
|
|
{
|
|
SLONG percent;
|
|
SLONG pitch;
|
|
|
|
if (p_person->State == STATE_GRAPPLING &&
|
|
p_person->SubState == SUB_STATE_GRAPPLING_WINDUP)
|
|
{
|
|
//
|
|
// How far through the animation is Darci?
|
|
//
|
|
|
|
percent = p_person->Draw.Tweened->FrameIndex << 8;
|
|
percent |= p_person->Draw.Tweened->AnimTween;
|
|
pitch = (-percent * 2048) / 0x500;
|
|
pitch &= 2047;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Make the hook hang down.
|
|
//
|
|
|
|
pitch = 1536;
|
|
}
|
|
|
|
//
|
|
// Make sure the hook is connected to Darci's right hand.
|
|
//
|
|
|
|
SLONG px;
|
|
SLONG py;
|
|
SLONG pz;
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_RIGHT_HAND,
|
|
&px,
|
|
&py,
|
|
&pz);
|
|
|
|
px += p_person->WorldPos.X >> 8;
|
|
py += p_person->WorldPos.Y >> 8;
|
|
pz += p_person->WorldPos.Z >> 8;
|
|
|
|
HOOK_spin(
|
|
px,
|
|
py,
|
|
pz,
|
|
p_person->Draw.Tweened->Angle,
|
|
-pitch);
|
|
}
|
|
#endif
|
|
/*
|
|
|
|
//if( (THING_NUMBER(p_person)&0x7) == (GAME_TURN&0x7) )
|
|
if(p_person->Genus.Person->PlayerID==0)
|
|
{
|
|
if (p_person->State == STATE_IDLE)
|
|
{
|
|
//
|
|
// Follow the player?
|
|
//
|
|
|
|
do_look_for_enemies(p_person);
|
|
|
|
if (ControlFlag)
|
|
{
|
|
TRACE("Looking for enemies\n");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Too far from home?
|
|
//
|
|
|
|
show_me_the_way_to_go_home(p_person);
|
|
}
|
|
|
|
*/
|
|
|
|
if( (p_person->Genus.Person->Action!=ACTION_RUN_JUMP) && (p_person->Genus.Person->Action!=ACTION_FIGHT_PUNCH) && (p_person->Genus.Person->Action!=ACTION_GRAPPLE))
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_KICK;
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
#ifndef PSX
|
|
if (GAME_FLAGS & GF_SEWERS)
|
|
{
|
|
if ((p_person->Flags & FLAGS_IN_SEWERS) && p_person->State != STATE_IDLE)
|
|
{
|
|
SLONG i;
|
|
SLONG j;
|
|
SLONG angle;
|
|
|
|
ULONG bit;
|
|
ULONG newsewerbits;
|
|
ULONG oldsewerbits = p_person->Genus.Person->sewerbits;
|
|
|
|
SLONG partx;
|
|
SLONG party;
|
|
SLONG partz;
|
|
|
|
SLONG sheight = NS_calc_splash_height_at(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
|
|
//
|
|
// Work out which body parts of the person are under water.
|
|
//
|
|
|
|
bit = 1;
|
|
newsewerbits = 0;
|
|
|
|
for (i = 0; i < 15; i++)
|
|
{
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
i,
|
|
&partx,
|
|
&party,
|
|
&partz);
|
|
|
|
partx += p_person->WorldPos.X >> 8;
|
|
party += p_person->WorldPos.Y >> 8;
|
|
partz += p_person->WorldPos.Z >> 8;
|
|
|
|
if (party < sheight)
|
|
{
|
|
newsewerbits |= bit;
|
|
|
|
if (oldsewerbits & bit)
|
|
{
|
|
if (((GAME_TURN + i) & 0x3) == 2)
|
|
{
|
|
DRIP_create(
|
|
partx,
|
|
sheight,
|
|
partz);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This limb is entering the water for the first time.
|
|
// make a splash.
|
|
//
|
|
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
angle = rand() & 2047;
|
|
|
|
DIRT_new_water(
|
|
partx,
|
|
sheight,
|
|
partz,
|
|
SIN(angle) >> 14,
|
|
14,
|
|
COS(angle) >> 14);
|
|
}
|
|
|
|
DRIP_create(
|
|
partx,
|
|
sheight,
|
|
partz);
|
|
}
|
|
}
|
|
|
|
bit <<= 1;
|
|
}
|
|
|
|
p_person->Genus.Person->sewerbits = newsewerbits;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
*/
|
|
|
|
/*
|
|
if (!(p_person->Flags & FLAGS_IN_SEWERS))
|
|
{
|
|
SLONG sx = p_person->WorldPos.X >> 16;
|
|
SLONG sz = p_person->WorldPos.Z >> 16;
|
|
|
|
ASSERT(WITHIN(sx, 0, PAP_SIZE_HI - 1));
|
|
ASSERT(WITHIN(sz, 0, PAP_SIZE_HI - 1));
|
|
|
|
if (p_person->State == STATE_CLIMB_LADDER)
|
|
{
|
|
//
|
|
// Let the climb ladder function handle this eventuality.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
if (PAP_2HI(sx,sz).Flags & PAP_FLAG_SEWER_SQUARE)
|
|
{
|
|
SLONG bottom = PAP_calc_height_at(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Z >> 8) << 8;
|
|
|
|
if (p_person->WorldPos.Y < bottom + 0x6000)
|
|
{
|
|
//
|
|
// This person is entering the sewers.
|
|
//
|
|
|
|
p_person->Flags |= FLAGS_IN_SEWERS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
general_process_player(p_person);
|
|
}
|
|
|
|
}
|
|
|
|
SLONG check_on_slippy_slope(Thing *p_person)
|
|
{
|
|
SLONG slope,angle;
|
|
SLONG size=50;
|
|
|
|
if(p_person->Genus.Person->InsideIndex)
|
|
{
|
|
slope=0;
|
|
}
|
|
else
|
|
{
|
|
if(p_person->OnFace<0)
|
|
{
|
|
slope=RFACE_on_slope(-p_person->OnFace,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle);
|
|
}
|
|
else
|
|
{
|
|
|
|
slope=PAP_on_slope(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle)>>1;
|
|
}
|
|
}
|
|
|
|
|
|
if(slope>size) // Change 50 here and change the 50 in MAV_precalculate...
|
|
{
|
|
switch(p_person->SubState)
|
|
{
|
|
default:
|
|
case SUB_STATE_RUNNING_JUMP:
|
|
case SUB_STATE_RUNNING_JUMP_LAND_FAST:
|
|
case SUB_STATE_RUNNING_JUMP_LAND:
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
case SUB_STATE_RUNNING:
|
|
case SUB_STATE_WALKING:
|
|
case SUB_STATE_WALKING_BACKWARDS:
|
|
case SUB_STATE_FLIPING:
|
|
case SUB_STATE_RUNNING_SKID_STOP:
|
|
|
|
set_anim(p_person,ANIM_FALLING);
|
|
|
|
case SUB_STATE_SLIPPING:
|
|
p_person->SubState=SUB_STATE_SLIPPING;
|
|
p_person->Draw.Tweened->AngleTo=angle;
|
|
|
|
slope=MIN(slope-size,10);
|
|
slope=MAX(slope,size);
|
|
|
|
|
|
change_velocity_to(p_person,slope);
|
|
|
|
// p_person->Velocity=MIN(slope-50,40);
|
|
break;
|
|
}
|
|
|
|
if(p_person->OnFace==0 &&p_person->Genus.Person->Ware==0)
|
|
if (PAP_2HI((p_person->WorldPos.X >> 16)&127, (p_person->WorldPos.Z >> 16)&127).Flags & PAP_FLAG_NOGO)
|
|
{
|
|
//
|
|
// shit its a nogo, so lets ping to nearest normal space
|
|
//
|
|
SLONG angle,step;
|
|
for(step=64;step<512;step+=64)
|
|
{
|
|
for(angle=0;angle<2048;angle+=256)
|
|
{
|
|
SLONG dx,dz;
|
|
dx=(COS(angle)*step)>>8;
|
|
dz=(SIN(angle)*step)>>8;
|
|
if (!(PAP_2HI(((p_person->WorldPos.X+dx) >> 16)&127, ((p_person->WorldPos.Z+dz) >> 16)&127).Flags & PAP_FLAG_NOGO))
|
|
{
|
|
GameCoord newpos;
|
|
|
|
slope=PAP_on_slope((p_person->WorldPos.X+dx)>>8,(p_person->WorldPos.Z+dz)>>8,&angle)>>1;
|
|
if(slope<40)
|
|
{
|
|
|
|
|
|
newpos.X = p_person->WorldPos.X+dx;
|
|
newpos.Z = p_person->WorldPos.Z+dz;
|
|
newpos.Y = PAP_calc_map_height_at(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8);
|
|
|
|
move_thing_on_map(p_person, &newpos);
|
|
|
|
step=50000;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
else
|
|
if(p_person->SubState==SUB_STATE_SLIPPING)
|
|
{
|
|
p_person->SubState=SUB_STATE_SLIPPING_END;
|
|
//set_person_idle(p_person);
|
|
}
|
|
return(0);
|
|
|
|
}
|
|
SLONG slope_ahead(Thing *p_person,SLONG dist)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG slippy;
|
|
|
|
dx = -(SIN(p_person->Draw.Tweened->Angle) * dist) >> 8;
|
|
dz = -(COS(p_person->Draw.Tweened->Angle) * dist) >> 8;
|
|
|
|
p_person->WorldPos.X+=dx;
|
|
p_person->WorldPos.Z+=dz;
|
|
|
|
slippy=check_on_slippy_slope(p_person);
|
|
|
|
p_person->WorldPos.X-=dx;
|
|
p_person->WorldPos.Z-=dz;
|
|
|
|
return(slippy);
|
|
|
|
}
|
|
void person_normal_move_dxdz(Thing *p_person,SLONG dx,SLONG dz)
|
|
{
|
|
// SLONG i;
|
|
|
|
SLONG dy;
|
|
SLONG new_y;
|
|
SLONG on_face;
|
|
|
|
// SLONG x1, y1, z1;
|
|
// SLONG x2, y2, z2;
|
|
|
|
// GameCoord new_position;
|
|
|
|
// Thing *col_thing;
|
|
slide_ladder=0;
|
|
|
|
if (p_person->Draw.Tweened->Locked)
|
|
{
|
|
//
|
|
// The movement is part of the animation.
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_HIT_WALL;
|
|
|
|
dy = 0;
|
|
|
|
|
|
//
|
|
// Move the person slower if he is at the wrong angle.
|
|
//
|
|
|
|
SLONG dangle = p_person->Draw.Tweened->AngleTo - p_person->Draw.Tweened->Angle;
|
|
SLONG dspeed = 300 - abs(dangle);
|
|
|
|
SATURATE(dspeed, 0, 256);
|
|
|
|
SLONG ratio = TICK_RATIO * dspeed >> 8;
|
|
|
|
//
|
|
// Don't do this ratio thing!
|
|
//
|
|
|
|
ratio = TICK_RATIO;
|
|
|
|
dx = dx * ratio >> TICK_SHIFT;
|
|
dz = dz * ratio >> TICK_SHIFT;
|
|
|
|
#ifndef PSX
|
|
if(allow_debug_keys)
|
|
if (ShiftFlag && Keys[KB_Q])
|
|
{
|
|
dx <<= 2;
|
|
dz <<= 2;
|
|
}
|
|
#endif
|
|
//
|
|
// Work out our new y-position.
|
|
//
|
|
|
|
if(p_person->OnFace)
|
|
{
|
|
if(p_person->OnFace>0)
|
|
{
|
|
on_face = calc_height_on_face(
|
|
(p_person->WorldPos.X + dx) >> 8,
|
|
(p_person->WorldPos.Z + dz) >> 8,
|
|
p_person->OnFace,
|
|
&new_y);
|
|
}
|
|
else
|
|
{
|
|
on_face = calc_height_on_rface(
|
|
(p_person->WorldPos.X + dx) >> 8,
|
|
(p_person->WorldPos.Z + dz) >> 8,
|
|
-p_person->OnFace,
|
|
&new_y);
|
|
|
|
}
|
|
|
|
if (!on_face)
|
|
{
|
|
//
|
|
// we have walked off the face we were on, so we leave it to move thing to sort out what happens next
|
|
//
|
|
|
|
new_y=p_person->WorldPos.Y;
|
|
}
|
|
else
|
|
{
|
|
MSG_add("normal move height %d \n",new_y);
|
|
new_y = (new_y ) <<8; //remove +4
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
if (p_person->Genus.Person->InsideIndex)
|
|
{
|
|
// ASSERT(p_person->Genus.Person->InsideIndex==1);
|
|
new_y = get_inside_alt(p_person->Genus.Person->InsideIndex)<<8;
|
|
}
|
|
else
|
|
if (p_person->Flags & FLAGS_IN_SEWERS)
|
|
{
|
|
new_y = NS_calc_height_at(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<<8;
|
|
}
|
|
else
|
|
{
|
|
new_y = PAP_calc_height_at(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<<8;
|
|
}
|
|
*/
|
|
{
|
|
SLONG mx,mz;
|
|
|
|
mx=(p_person->WorldPos.X+dx) >> 16;
|
|
mz=(p_person->WorldPos.Z+dz) >> 16;
|
|
mx&=127;
|
|
mz&=127;
|
|
|
|
|
|
if (PAP_2HI(mx,mz).Flags & PAP_FLAG_HIDDEN)
|
|
new_y = PAP_calc_height_at_thing(p_person,(p_person->WorldPos.X+0*dx)>>8,(p_person->WorldPos.Z+0*dz)>>8)<<8; //shit miked aug 2000 wasnt adding dx dz
|
|
else
|
|
new_y = PAP_calc_height_at_thing(p_person,(p_person->WorldPos.X+dx)>>8,(p_person->WorldPos.Z+dz)>>8)<<8; //shit miked aug 2000 wasnt adding dx dz
|
|
}
|
|
}
|
|
|
|
//
|
|
// Work out the change in our height.
|
|
//
|
|
|
|
dy = new_y - p_person->WorldPos.Y;
|
|
|
|
// if(p_person->SubState!=SUB_STATE_WALKING)
|
|
if(p_person->SubState!=SUB_STATE_SLIPPING)
|
|
if(dy<-60<<8)
|
|
{
|
|
|
|
// p_person->Velocity=20;
|
|
set_person_drop_down(p_person,PERSON_DROP_DOWN_KEEP_VEL);
|
|
return;
|
|
}
|
|
/*
|
|
if(dy>16<<8)
|
|
{
|
|
if(p_person->SubState==SUB_STATE_WALKING||p_person->SubState==SUB_STATE_RUNNING)
|
|
{
|
|
//
|
|
// don't ping up big steps, take them with style
|
|
//
|
|
dx=0;
|
|
dz=0;
|
|
dy=16<<8;
|
|
}
|
|
}
|
|
*/
|
|
|
|
// if(abs(dy)>60<<8)
|
|
// return;
|
|
|
|
// ASSERT(abs(dy>>8)<256);
|
|
/*
|
|
//
|
|
// If our change-in-height is too big, then don't move.
|
|
//
|
|
|
|
#define PERSON_MAX_HEIGHT_CHANGE 40
|
|
|
|
if (!(p_person->Genus.Person->InsideIndex))
|
|
if (dy > (PERSON_MAX_HEIGHT_CHANGE << 8))
|
|
{
|
|
return;
|
|
}
|
|
*/
|
|
//
|
|
// Actually move the person.
|
|
//
|
|
|
|
if (dx || dz)
|
|
{
|
|
/*
|
|
SLONG slope=0,angle;
|
|
if(p_person->SubState!=SUB_STATE_SLIPPING && dy)
|
|
{
|
|
|
|
if(p_person->OnFace<0)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
|
|
slope=PAP_on_slope((p_person->WorldPos.X+dx)>>8,(p_person->WorldPos.Z+dz)>>8,&angle)>>1;
|
|
}
|
|
}
|
|
if(slope<50)
|
|
*/
|
|
move_thing(dx,dy,dz,p_person);
|
|
}
|
|
|
|
if(dy||p_person->Genus.Person->PlayerID)
|
|
{
|
|
check_on_slippy_slope(p_person);
|
|
|
|
/*
|
|
SLONG slope,angle;
|
|
|
|
if(p_person->Genus.Person->InsideIndex)
|
|
{
|
|
slope=0;
|
|
}
|
|
else
|
|
{
|
|
if(p_person->OnFace<0)
|
|
{
|
|
slope=RFACE_on_slope(-p_person->OnFace,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle);
|
|
}
|
|
else
|
|
{
|
|
|
|
slope=PAP_on_slope(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle);
|
|
}
|
|
}
|
|
|
|
if(slope>50)
|
|
{
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_RUNNING:
|
|
case SUB_STATE_WALKING:
|
|
case SUB_STATE_WALKING_BACKWARDS:
|
|
case SUB_STATE_RUNNING_JUMP_LAND_FAST:
|
|
case SUB_STATE_RUNNING_JUMP_LAND:
|
|
set_anim(p_person,ANIM_FALLING);
|
|
case SUB_STATE_SLIPPING:
|
|
p_person->SubState=SUB_STATE_SLIPPING;
|
|
p_person->Draw.Tweened->AngleTo=angle;
|
|
|
|
slope=MIN(slope-50,40);
|
|
slope=MAX(slope,10);
|
|
|
|
|
|
change_velocity_to(p_person,slope);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
|
|
// p_person->Velocity=MIN(slope-50,40);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
if(p_person->SubState==SUB_STATE_SLIPPING)
|
|
{
|
|
p_person->SubState=SUB_STATE_SLIPPING_END;
|
|
//set_person_idle(p_person);
|
|
}
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
if(p_person->SubState==SUB_STATE_SLIPPING)
|
|
{
|
|
SLONG slope,angle;
|
|
if(p_person->Genus.Person->InsideIndex)
|
|
{
|
|
slope=0;
|
|
}
|
|
else
|
|
{
|
|
|
|
if(p_person->OnFace<0)
|
|
{
|
|
slope=RFACE_on_slope(-p_person->OnFace,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle);
|
|
}
|
|
else
|
|
{
|
|
|
|
slope=PAP_on_slope(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle)>>1;
|
|
}
|
|
}
|
|
|
|
if(slope<=50)
|
|
p_person->SubState=SUB_STATE_SLIPPING_END;
|
|
//set_person_idle(p_person);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void person_normal_move(Thing *p_person)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
|
|
dx = -(SIN(p_person->Draw.Tweened->Angle) * p_person->Velocity) >> 8;
|
|
dz = -(COS(p_person->Draw.Tweened->Angle) * p_person->Velocity) >> 8;
|
|
person_normal_move_dxdz(p_person,dx,dz);
|
|
}
|
|
|
|
void person_normal_move_check(Thing *p_person)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG x,z;
|
|
|
|
dx = -(SIN(p_person->Draw.Tweened->Angle) * p_person->Velocity) >> 8;
|
|
dz = -(COS(p_person->Draw.Tweened->Angle) * p_person->Velocity) >> 8;
|
|
x=dx+p_person->WorldPos.X;
|
|
z=dz+p_person->WorldPos.Z;
|
|
|
|
if(x<0||z<0||x>=(128<<16)||z>=(128<<16))
|
|
return;
|
|
|
|
person_normal_move_dxdz(p_person,dx,dz);
|
|
}
|
|
|
|
SLONG advance_keyframe(DrawTween *draw_info)
|
|
{
|
|
SLONG ret=0;
|
|
draw_info->CurrentFrame = draw_info->NextFrame;
|
|
if(draw_info->QueuedFrame)
|
|
{
|
|
draw_info->NextFrame = draw_info->QueuedFrame;
|
|
draw_info->QueuedFrame = 0;
|
|
draw_info->FrameIndex = 0; //if we are leaping into the middle of an anim then this should have a value
|
|
ret=2; //anim has ended
|
|
ASSERT(draw_info->CurrentFrame->FirstElement);
|
|
ASSERT(draw_info->NextFrame->FirstElement);
|
|
|
|
}
|
|
else
|
|
{
|
|
if(draw_info->NextFrame->NextFrame)
|
|
{
|
|
// LogText(" do next frame \n");
|
|
draw_info->NextFrame = draw_info->NextFrame->NextFrame;
|
|
if(draw_info->CurrentFrame->Flags&ANIM_FLAG_LAST_FRAME)
|
|
ret=1; // hopefully escape funny lock out situations by saying a looped anim has ended
|
|
|
|
}
|
|
else
|
|
ret=1; //anim has ended
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
SLONG retreat_keyframe(DrawTween *draw_info)
|
|
{
|
|
SLONG ret=0;
|
|
draw_info->NextFrame = draw_info->CurrentFrame;
|
|
if(draw_info->QueuedFrame)
|
|
{
|
|
// draw_info->NextFrame = draw_info->QueuedFrame;
|
|
// draw_info->QueuedFrame = 0;
|
|
// draw_info->FrameIndex = 0; //if we are leaping into the middle of an anim then this should have a value
|
|
}
|
|
else
|
|
{
|
|
if(draw_info->CurrentFrame->PrevFrame)
|
|
{
|
|
// LogText(" do next frame \n");
|
|
draw_info->CurrentFrame = draw_info->CurrentFrame->PrevFrame;
|
|
}
|
|
else
|
|
{
|
|
ret=1; //anim has ended
|
|
// MSG_add(" backwards anim ends \n");
|
|
}
|
|
}
|
|
return(ret);
|
|
}
|
|
extern void calc_sub_objects_position_fix8(Thing *p_mthing,SLONG tween,UWORD object,SLONG *x,SLONG *y,SLONG *z);
|
|
|
|
void move_locked_tween(Thing *p_person,DrawTween *dt,SLONG t1,SLONG t2)
|
|
{
|
|
SLONG x1, y1, z1;
|
|
SLONG x2, y2, z2;
|
|
SLONG dx,dy,dz;
|
|
|
|
// calc_sub_objects_position(p_person,tween1,locked,&lock_x1,&lock_y1,&lock_z1);
|
|
// calc_sub_objects_position(p_person,tween1,locked,&lock_x1,&lock_y1,&lock_z1);
|
|
|
|
calc_sub_objects_position_fix8(p_person, t1, abs(dt->Locked), &x1, &y1, &z1);
|
|
calc_sub_objects_position_fix8(p_person, t2, abs(dt->Locked), &x2, &y2, &z2);
|
|
|
|
// calc_sub_objects_position_global(dt->CurrentFrame, dt->NextFrame, t1, abs(dt->Locked), &x1, &y1, &z1);
|
|
// calc_sub_objects_position_global(dt->CurrentFrame, dt->NextFrame, t2, abs(dt->Locked), &x2, &y2, &z2);
|
|
|
|
dx = (x1 - x2); //<<8;
|
|
dy = (y1 - y2); //<<8;
|
|
dz = (z1 - z2); //<<8;
|
|
|
|
if(abs(dy)>600<<8)
|
|
{
|
|
ASSERT(0);
|
|
calc_sub_objects_position_fix8(p_person, t1, abs(dt->Locked), &x1, &y1, &z1);
|
|
calc_sub_objects_position_fix8(p_person, t2, abs(dt->Locked), &x2, &y2, &z2);
|
|
|
|
}
|
|
if(p_person->State==STATE_DANGLING)
|
|
{
|
|
move_thing_quick(dx,dy,dz,p_person);
|
|
MSG_add(" mtq dx %d dy %d dz %d \n",dx,dy,dz);
|
|
}
|
|
else
|
|
{
|
|
move_thing(dx,dy,dz,p_person);
|
|
MSG_add(" mt dx %d dy %d dz %d \n",dx,dy,dz);
|
|
}
|
|
}
|
|
|
|
|
|
SLONG person_normal_animate_speed(Thing *p_person,SLONG speed)
|
|
{
|
|
SLONG ret=0;
|
|
DrawTween *draw_info;
|
|
SLONG old_tween;
|
|
SLONG dx,dy,dz;
|
|
SLONG tween1,tween2;
|
|
|
|
// speed=256;
|
|
|
|
|
|
draw_info = p_person->Draw.Tweened;
|
|
|
|
if(draw_info->CurrentFrame==0 || draw_info->NextFrame==0)
|
|
{
|
|
MSG_add(" !!!!!!!!!!!!!!!!!!!!!!error2 animate 0 frames \n");
|
|
return(1);
|
|
}
|
|
old_tween = draw_info->AnimTween;
|
|
|
|
{
|
|
//SLONG tween_step=speed/(draw_info->CurrentFrame->TweenStep+1);
|
|
SLONG tween_step=draw_info->CurrentFrame->TweenStep<<1;
|
|
|
|
tween1=draw_info->AnimTween;
|
|
tween_step = (tween_step*TICK_RATIO)>>TICK_SHIFT;
|
|
if(tween_step<=0)
|
|
tween_step=1;
|
|
draw_info->AnimTween += tween_step; //256/(draw_info->CurrentFrame->TweenStep+1);
|
|
tween2=draw_info->AnimTween;
|
|
if(draw_info->Locked&&draw_info->AnimTween<256)
|
|
{
|
|
move_locked_tween(p_person,draw_info,tween1,tween2);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// If anim has tweened over to the next frame
|
|
//
|
|
// while(draw_info->AnimTween>=256)
|
|
while(tween2>=256)
|
|
{
|
|
SLONG lock_x1,lock_y1,lock_z1,lock_x2,lock_y2,lock_z2;
|
|
// MSG_add(" next frame \n");
|
|
|
|
// draw_info->AnimTween -= 256;
|
|
tween2-=256;
|
|
|
|
if(draw_info->NextFrame)
|
|
tween2=(tween2*draw_info->NextFrame->TweenStep)/draw_info->CurrentFrame->TweenStep;
|
|
draw_info->AnimTween = tween2;
|
|
|
|
if(draw_info->CurrentFrame->Flags&ANIM_FLAG_LAST_FRAME)
|
|
{
|
|
// LogText(" at frame %d flagged as last frame \n",draw_info->FrameIndex);
|
|
draw_info->FrameIndex=0;
|
|
}
|
|
else
|
|
{
|
|
draw_info->FrameIndex++;
|
|
}
|
|
|
|
if(draw_info->Locked)
|
|
{
|
|
GameCoord temp_pos;
|
|
SLONG locked;
|
|
|
|
locked=abs(draw_info->Locked);
|
|
|
|
calc_sub_objects_position_fix8(p_person,tween1,locked,&lock_x1,&lock_y1,&lock_z1);
|
|
ret|=advance_keyframe(draw_info);
|
|
calc_sub_objects_position_fix8(p_person,tween2,draw_info->Locked,&lock_x2,&lock_y2,&lock_z2);
|
|
|
|
dx=(+lock_x1-lock_x2);//<<8;
|
|
dy=(+lock_x1-lock_x2);//<<8;
|
|
dz=(+lock_x1-lock_x2);//<<8;
|
|
|
|
if(p_person->State==STATE_DANGLING)
|
|
{
|
|
MSG_add("MOVE THING QUICK dx %d dy %d dz %d \n",dx,dy,dz);
|
|
move_thing_quick(dx,dy,dz,p_person);
|
|
}
|
|
else
|
|
{
|
|
move_thing(dx,dy,dz,p_person);
|
|
MSG_add("MOVE THING dx %d dy %d dz %d \n",dx,dy,dz);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
ret|=advance_keyframe(draw_info);
|
|
}
|
|
|
|
if(draw_info->CurrentFrame->Fight)
|
|
{
|
|
// PlaySample(THING_NUMBER(p_person),SAMPLE_HIT_MISS1,SAMPLE_VOL_MAX,SAMPLE_PAN_CENTER,SAMPLE_FREQ_ORIG+(GAME_TURN&0xfff),0);
|
|
if(apply_violence(p_person)==0)
|
|
{
|
|
#ifndef PSX
|
|
extern BOOL PLAYCUTS_playing;
|
|
#ifdef EDITOR
|
|
extern HWND CUTSCENE_edit_wnd;
|
|
if (!(CUTSCENE_edit_wnd||PLAYCUTS_playing))
|
|
#else
|
|
if (!PLAYCUTS_playing)
|
|
#endif
|
|
#endif
|
|
MFX_play_thing(THING_NUMBER(p_person),S_KNIFE_START+(Random()&1),0,p_person);
|
|
//
|
|
// we missed
|
|
//
|
|
// p_person->Genus.Person->CombatNode=-p_person->Genus.Person->CombatNode;
|
|
|
|
}
|
|
|
|
//
|
|
// Knock over barrels!
|
|
//
|
|
|
|
BARREL_hit_with_sphere(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
0xa0); // Bigger than normal
|
|
}
|
|
}
|
|
|
|
if (ret == 1)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
return(ret);
|
|
}
|
|
|
|
|
|
SLONG person_normal_animate(Thing *p_person)
|
|
{
|
|
return(person_normal_animate_speed(p_person,256));
|
|
}
|
|
|
|
SLONG person_backwards_animate(Thing *p_person)
|
|
{
|
|
SLONG ret=0;
|
|
DrawTween *draw_info;
|
|
SLONG old_tween;
|
|
SLONG tween_step;
|
|
|
|
draw_info = p_person->Draw.Tweened;
|
|
|
|
if(draw_info->CurrentFrame==NULL)
|
|
{
|
|
MSG_add(" backwards anim crash");
|
|
return(1);
|
|
|
|
}
|
|
//tween_step=256/(draw_info->CurrentFrame->TweenStep+1);
|
|
tween_step=draw_info->CurrentFrame->TweenStep<<1;
|
|
|
|
tween_step=(tween_step*TICK_RATIO)>>TICK_SHIFT;
|
|
|
|
|
|
|
|
old_tween = draw_info->AnimTween;
|
|
|
|
draw_info->AnimTween -= tween_step; //256/(draw_info->CurrentFrame->TweenStep+1);
|
|
|
|
//LogText(" animate person tween %d current_anim %d currentframe %x\n",draw_info->AnimTween,draw_info->CurrentAnim,draw_info->CurrentFrame);
|
|
|
|
//
|
|
// If anim has tweened over to the next frame
|
|
//
|
|
while(draw_info->AnimTween<0)
|
|
{
|
|
SLONG lock_x1,lock_y1,lock_z1,lock_x2,lock_y2,lock_z2;
|
|
|
|
draw_info->AnimTween += 256;
|
|
|
|
if(draw_info->CurrentFrame->Flags&ANIM_FLAG_LAST_FRAME)
|
|
{
|
|
draw_info->FrameIndex=0;
|
|
}
|
|
else
|
|
{
|
|
draw_info->FrameIndex++;
|
|
}
|
|
|
|
if(draw_info->Locked)
|
|
{
|
|
GameCoord temp_pos;
|
|
SLONG locked;
|
|
//
|
|
// Part of body is locked in place so across anim maintain its location
|
|
//
|
|
|
|
locked=abs(draw_info->Locked);
|
|
|
|
calc_sub_objects_position(p_person,0,locked,&lock_x1,&lock_y1,&lock_z1);
|
|
calc_sub_objects_position(p_person,256,locked,&lock_x2,&lock_y2,&lock_z2);
|
|
ret=retreat_keyframe(draw_info);
|
|
|
|
//
|
|
// difference in lock co-ord is ammount to move by to maintain same position for limb
|
|
//
|
|
|
|
temp_pos.X=((+lock_x1-lock_x2)<<8)+p_person->WorldPos.X;
|
|
temp_pos.Y=((+lock_y1-lock_y2)<<8)+p_person->WorldPos.Y;
|
|
temp_pos.Z=((+lock_z1-lock_z2)<<8)+p_person->WorldPos.Z;
|
|
|
|
//LogText(" old lock %d %d %d \n",lock_x1,lock_y1,lock_z1);
|
|
//LogText(" new lock %d %d %d \n",lock_x2,lock_y2,lock_z2);
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
}
|
|
else
|
|
ret=retreat_keyframe(draw_info);
|
|
|
|
if(draw_info->CurrentFrame->Fight)
|
|
{
|
|
apply_violence(p_person);
|
|
}
|
|
|
|
}
|
|
// MSG_add(" backwards returns %d \n",ret);
|
|
return(ret);
|
|
}
|
|
|
|
void camera_shoot(void)
|
|
{
|
|
/*
|
|
|
|
Thing *darci;
|
|
|
|
SLONG map_x;
|
|
SLONG map_z;
|
|
|
|
darci = NET_PERSON(0);
|
|
|
|
map_x = darci->WorldPos.X >> 16;
|
|
map_z = darci->WorldPos.Z >> 16;
|
|
|
|
if (PAP_2HI(map_x, map_z).Flags & PAP_FLAG_NAUGHTY)
|
|
{
|
|
//
|
|
// No point doing this indoors...
|
|
//
|
|
}
|
|
else
|
|
{
|
|
CAM_set_mode(CAM_MODE_SHOOT_NORMAL);
|
|
CAM_set_zoom(0x320);
|
|
CAM_set_behind_up(0x30000);
|
|
CAM_lens = CAM_LENS_NORMAL;
|
|
}
|
|
*/
|
|
}
|
|
|
|
void camera_fight(void)
|
|
{
|
|
|
|
/*
|
|
Thing *darci;
|
|
|
|
SLONG map_x;
|
|
SLONG map_z;
|
|
|
|
darci = NET_PERSON(0);
|
|
|
|
map_x = darci->WorldPos.X >> 16;
|
|
map_z = darci->WorldPos.Z >> 16;
|
|
|
|
if (PAP_2HI(map_x, map_z).Flags & PAP_FLAG_NAUGHTY)
|
|
{
|
|
//
|
|
// No point doing this indoors...
|
|
//
|
|
}
|
|
else
|
|
{
|
|
CAM_set_mode(CAM_MODE_FIGHT_NORMAL);
|
|
CAM_set_zoom(0x320);
|
|
CAM_set_behind_up(0x70000);
|
|
CAM_lens = CAM_LENS_NORMAL;
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
void camera_normal(void)
|
|
{
|
|
/*
|
|
#ifndef PSX
|
|
Thing *darci;
|
|
|
|
SLONG map_x;
|
|
SLONG map_z;
|
|
|
|
darci = NET_PERSON(0);
|
|
|
|
map_x = darci->WorldPos.X >> 16;
|
|
map_z = darci->WorldPos.Z >> 16;
|
|
|
|
if (PAP_2HI(map_x, map_z).Flags & PAP_FLAG_NAUGHTY)
|
|
{
|
|
CAM_set_mode(CAM_MODE_BEHIND);
|
|
CAM_set_zoom(0x340 * 180 / 256);
|
|
CAM_set_behind_up(0x18000 * 100 / 256);
|
|
CAM_lens = CAM_LENS_WIDEANGLE;
|
|
CAM_set_collision(FALSE);
|
|
}
|
|
else
|
|
{
|
|
CAM_set_type(CAM_get_type());
|
|
}
|
|
#endif
|
|
*/
|
|
}
|
|
|
|
|
|
void set_person_aim(Thing *p_person,SLONG locked=0)
|
|
{
|
|
SLONG anim;
|
|
Thing *p_special;
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
//
|
|
// It must be a two-handed shotgun weapon.
|
|
//
|
|
/*
|
|
if ((p_person->Genus.Person->PersonType==PERSON_ROPER)&&((p_person->Draw.Tweened->PersonID>>5)==5)) {
|
|
// ...but roper's so fucking 'ard he uses an ak47 one-handed.
|
|
// of course, it should break his arm when he fires, but hey.
|
|
anim = ANIM_AK_AIM;
|
|
} else {
|
|
anim = ANIM_SHOTGUN_AIM;
|
|
}
|
|
*/
|
|
anim = ANIM_SHOTGUN_AIM;
|
|
|
|
}
|
|
else
|
|
{
|
|
anim = ANIM_PISTOL_AIM_AHEAD;
|
|
}
|
|
|
|
set_generic_person_state_function(p_person,STATE_GUN);
|
|
if(locked)
|
|
set_locked_anim(p_person,anim,locked-1);
|
|
else
|
|
set_anim(p_person,anim);
|
|
|
|
p_person->Genus.Person->Action = ACTION_AIM_GUN;
|
|
p_person->SubState = SUB_STATE_AIM_GUN;
|
|
p_person->Genus.Person->Flags &= ~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
// p_person->Genus.Person->Flags |= (FLAG_PERSON_NON_INT_C);
|
|
}
|
|
|
|
inline SLONG weapon_accuracy_at_dist(Thing *p_person,SLONG dist)
|
|
{
|
|
if(dist<0)
|
|
return(dist);
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
//
|
|
// Using a special.
|
|
//
|
|
|
|
switch (p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_AK47:
|
|
if(!p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// AI needs high skill to use this well
|
|
//
|
|
|
|
return((dist*(280-(GET_SKILL(p_person)<<2)))>>8);
|
|
}
|
|
else
|
|
{
|
|
return((dist*200)>>8);
|
|
}
|
|
break;
|
|
|
|
case SPECIAL_SHOTGUN:
|
|
return(dist>>2);
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This must be the gun.
|
|
//
|
|
|
|
return(dist);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Returns the damage a person should do when he shoots his target.
|
|
// A damage of zero means that he missed the person.
|
|
//
|
|
|
|
UBYTE VehicleBelongsToMIB(Thing *p_target)
|
|
{
|
|
Vehicle *veh = p_target->Genus.Vehicle;
|
|
Thing *thing;
|
|
SWORD passenger;
|
|
|
|
if ((p_target->Class!=CLASS_VEHICLE)||!veh) return 0; // it's not even a vehicle, so it can't possibly be...
|
|
|
|
if (veh->Driver)
|
|
{
|
|
thing=TO_THING(veh->Driver);
|
|
if (PersonIsMIB(thing)) return 1; // it's being driven by a MIB
|
|
}
|
|
passenger=veh->Passenger;
|
|
while (passenger)
|
|
{
|
|
thing=TO_THING(passenger);
|
|
if (PersonIsMIB(thing)) return 1; // a MIB is riding shotgun
|
|
passenger=thing->Genus.Person->Passenger;
|
|
}
|
|
return 0; // nope, no MIBs
|
|
}
|
|
|
|
|
|
SLONG get_shoot_damage(Thing *p_person, Thing *p_target,SLONG *gun_type)
|
|
{
|
|
SLONG damage;
|
|
|
|
SLONG dx = abs(p_target->WorldPos.X - p_person->WorldPos.X >> 8);
|
|
SLONG dz = abs(p_target->WorldPos.Z - p_person->WorldPos.Z >> 8);
|
|
SLONG dist = QDIST2(dx,dz);
|
|
|
|
//
|
|
// Work out the chance of hitting our target.
|
|
//
|
|
|
|
{
|
|
SLONG chance; // 0 => Never hit, (>= 256) => Definitely hit
|
|
|
|
if (p_target->Class == CLASS_VEHICLE)
|
|
{
|
|
//
|
|
// Vehicle are too big not to miss!
|
|
//
|
|
|
|
/* apparently, we don't want this. cool, that way I don't have to test it... :}
|
|
|
|
if (VehicleBelongsToMIB(p_target))
|
|
{
|
|
chance=0;
|
|
// do some special effect here...
|
|
}
|
|
else*/
|
|
chance = 256;
|
|
}
|
|
else
|
|
if (p_target->Class == CLASS_BAT)
|
|
{
|
|
//
|
|
// Bats are tricky to hit!
|
|
//
|
|
|
|
// chance = 128;
|
|
chance = 200; //bats are just an annoyance, kill em easy just for fun, don't want to watse your ammo on these damn things
|
|
}
|
|
else
|
|
if (p_target->Class == CLASS_BARREL)
|
|
{
|
|
//
|
|
// Barrels tend to not move! So they are easy to hit.
|
|
//
|
|
|
|
chance = 200;
|
|
}
|
|
else
|
|
if (p_target->Class == CLASS_SPECIAL)
|
|
{
|
|
//
|
|
// Mines are really small!
|
|
//
|
|
|
|
// chance = 128;
|
|
chance = 250; //but you get to take a long time aiming sng get a clear shot against a stationary target
|
|
}
|
|
else
|
|
if (p_target->Class == CLASS_PERSON)
|
|
{
|
|
//
|
|
// People are trickier to hit if they are turning. A players
|
|
// Roll maxes out at about 100.
|
|
//
|
|
|
|
chance = 230 - (abs(p_target->Draw.Tweened->Roll)>>1); //180 for full turning person
|
|
|
|
//
|
|
//Moving person harder to hit
|
|
//
|
|
chance -=p_target->Velocity; //150 for run or down to 130 with sprint
|
|
|
|
|
|
//
|
|
// Non-player characters are a bad aim!
|
|
//
|
|
|
|
if (!p_person->Genus.Person->PlayerID)
|
|
{
|
|
if(p_target->Genus.Person->PlayerID)
|
|
{
|
|
chance -= 64; // enemies accuracy reduced for shooting player
|
|
}
|
|
else
|
|
{
|
|
chance+=100; //AI is very good at shooting other AI
|
|
}
|
|
chance +=GET_SKILL(p_person)<<3; // add on their skill factor
|
|
|
|
}
|
|
else
|
|
{
|
|
chance+=64; // player accuracy should be better than it currently is
|
|
}
|
|
if(p_target->SubState==SUB_STATE_FLIPING)
|
|
{
|
|
chance-=96;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This is an invalid target! It could be that the target was a
|
|
// barrel or a mine that was freed up before the person noticed.
|
|
//
|
|
|
|
p_person->Genus.Person->Target = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Make the chance of hitting the target depend on distance.
|
|
//
|
|
|
|
if(p_target->Genus.Person->PlayerID)
|
|
{
|
|
dist -= 0x2a0;
|
|
}
|
|
else
|
|
{
|
|
dist -= 0x400;
|
|
}
|
|
if(dist<0)
|
|
{
|
|
//
|
|
// -ve values are subtracted directly from chance
|
|
// so if you are at zero distance then chance will be 100%
|
|
// 2 blocks awayt is a 50% bonus
|
|
// 3 blocks is a 25% bonus
|
|
// 4 blocks break even
|
|
dist >>= 2;
|
|
}
|
|
else
|
|
{
|
|
dist >>= 3;
|
|
}
|
|
|
|
// dist is 0->8 blocks say so this is 0->(256*8-300)/8
|
|
// dist =0 ->218
|
|
|
|
//
|
|
// At 0x300 distance chance is unchanged. At 0x600 distance, chance is reduced
|
|
// by 37.5%
|
|
//
|
|
|
|
{
|
|
SLONG dchance;
|
|
dchance=chance;
|
|
chance -= weapon_accuracy_at_dist(p_person,dist);
|
|
// PANEL_new_text(p_person, 2000, "Chance of hitting you is%d%% with dist %d%% at dist %d",dchance * 100 >> 8, chance * 100 >> 8,dist);
|
|
}
|
|
|
|
if (p_target->State == STATE_MOVEING &&
|
|
p_target->SubState == SUB_STATE_FLIPING)
|
|
{
|
|
chance >>= 1;
|
|
}
|
|
|
|
SATURATE(chance, 20, 256); //always have a slim hope surely
|
|
|
|
//
|
|
// There is a chance the person will miss
|
|
//
|
|
|
|
if (chance < (Random() & 0xff))
|
|
{
|
|
//
|
|
// A miss!
|
|
//
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if(p_target->Genus.Player->PlayerID)
|
|
{
|
|
dist-=(300>>3);
|
|
}
|
|
|
|
|
|
//
|
|
// A hit. The damage depends on the gun.
|
|
//
|
|
|
|
if (PersonIsMIB(p_person))
|
|
{
|
|
//
|
|
// Men In Black all have AK47s
|
|
//
|
|
|
|
*gun_type = HIT_TYPE_GUN_SHOT_AK47;
|
|
damage = 40; // Rapid fire...
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
//
|
|
// Using a special.
|
|
//
|
|
|
|
switch (p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_AK47:
|
|
*gun_type=HIT_TYPE_GUN_SHOT_AK47;
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
damage = 100;
|
|
}
|
|
else
|
|
{
|
|
damage = 40; // Rapid fire...
|
|
}
|
|
break;
|
|
|
|
case SPECIAL_SHOTGUN:
|
|
*gun_type=HIT_TYPE_GUN_SHOT_SHOTGUN;
|
|
//
|
|
// shot gun depends on distance, lethal up close
|
|
//
|
|
|
|
// max range = (0x600-0x400)>>3 = 0x40 0x40<<2= 100
|
|
if(p_target->Genus.Player->PlayerID || p_person->Genus.Person->PlayerID)
|
|
{
|
|
dist<<=2;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// AI characters shooting each other can do lots of damage
|
|
//
|
|
}
|
|
damage = 300-(dist);//<<2); // One shot kills. was 250
|
|
SATURATE(damage,0,250);
|
|
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This must be the gun.
|
|
//
|
|
|
|
ASSERT(p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT);
|
|
|
|
*gun_type = HIT_TYPE_GUN_SHOT_PISTOL;
|
|
damage = 70; // Three shots kill...
|
|
}
|
|
|
|
if (p_target->Genus.Person->PlayerID)
|
|
{
|
|
damage >>= 1;
|
|
}
|
|
|
|
return damage;
|
|
}
|
|
|
|
|
|
#define NOT_A_GUN_YOU_SHOOT (-1)
|
|
#define HAD_TO_CHANGE_CLIP (-2)
|
|
|
|
SLONG shoot_get_ammo_sound_anim_time(Thing *p_person,SLONG *sound,SLONG *anim,SLONG *time)
|
|
{
|
|
SLONG ammo = FALSE;
|
|
SLONG ammo_in_clip;
|
|
|
|
if (PersonIsMIB(p_person))
|
|
{
|
|
//
|
|
// MIB all have ak47s with unlimited ammo!
|
|
//
|
|
|
|
*anim = ANIM_AK_FIRE;
|
|
ammo = 50;
|
|
*time = 64;
|
|
*sound = S_MIB_GUN_WDOWN;
|
|
|
|
return ammo;
|
|
}
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
//
|
|
// All specials use the shotgun sound?
|
|
//
|
|
|
|
*sound = S_SHOTGUN_SHOT;
|
|
|
|
//
|
|
// Using a special.
|
|
//
|
|
|
|
switch (p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_AK47:
|
|
|
|
if (p_person->Genus.Person->PlayerID == 0)
|
|
{
|
|
//
|
|
// Enemies never run out of AK ammo.
|
|
//
|
|
|
|
p_special->Genus.Special->ammo ++;
|
|
|
|
}
|
|
|
|
*anim = ANIM_AK_FIRE;
|
|
*time = 64;
|
|
// *sound = S_AK47_SHOT; // <- more 'accurate' but not as 'fun'
|
|
*sound = S_AK47_BURST;// <- sounds better overall
|
|
break;
|
|
|
|
case SPECIAL_SHOTGUN:
|
|
*anim = ANIM_SHOTGUN_FIRE;
|
|
*time = 400;
|
|
#ifndef BUILD_PSX
|
|
DIRT_new_sparks(p_person->Genus.Person->GunMuzzle.X>>8,p_person->Genus.Person->GunMuzzle.Y>>8,p_person->Genus.Person->GunMuzzle.Z>>8,2|32);
|
|
#endif
|
|
break;
|
|
|
|
case SPECIAL_GRENADE:
|
|
|
|
//
|
|
// This is the way non-players throw grenades...
|
|
//
|
|
|
|
SPECIAL_prime_grenade(p_special);
|
|
|
|
set_person_can_release(p_person, 128);
|
|
|
|
return NOT_A_GUN_YOU_SHOOT;
|
|
|
|
default:
|
|
|
|
//
|
|
// This isn't a weapon you shoot!
|
|
//
|
|
|
|
return NOT_A_GUN_YOU_SHOOT;
|
|
}
|
|
|
|
//
|
|
// Any ammo?
|
|
//
|
|
|
|
if (p_special->Genus.Special->ammo)
|
|
{
|
|
p_special->Genus.Special->ammo -= 1;
|
|
|
|
//
|
|
// We have ammo.
|
|
//
|
|
|
|
ammo = TRUE;
|
|
}
|
|
else
|
|
{
|
|
switch (p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_AK47:
|
|
if(p_person->Genus.Person->ammo_packs_ak47)
|
|
{
|
|
ammo_in_clip=p_person->Genus.Person->ammo_packs_ak47;
|
|
ammo_in_clip-=SPECIAL_AMMO_IN_A_AK47;
|
|
if (ammo_in_clip<0)
|
|
{
|
|
p_special->Genus.Special->ammo = p_person->Genus.Person->ammo_packs_ak47;
|
|
p_person->Genus.Person->ammo_packs_ak47 = 0;
|
|
}
|
|
else
|
|
{
|
|
p_special->Genus.Special->ammo = SPECIAL_AMMO_IN_A_AK47;
|
|
p_person->Genus.Person->ammo_packs_ak47 = ammo_in_clip;
|
|
}
|
|
|
|
ammo = HAD_TO_CHANGE_CLIP;
|
|
|
|
}
|
|
break;
|
|
case SPECIAL_SHOTGUN:
|
|
if(p_person->Genus.Person->ammo_packs_shotgun)
|
|
{
|
|
ammo_in_clip=p_person->Genus.Person->ammo_packs_shotgun;
|
|
ammo_in_clip-=SPECIAL_AMMO_IN_A_SHOTGUN;
|
|
if (ammo_in_clip<0)
|
|
{
|
|
p_special->Genus.Special->ammo = p_person->Genus.Person->ammo_packs_shotgun;
|
|
p_person->Genus.Person->ammo_packs_shotgun = 0;
|
|
}
|
|
else
|
|
{
|
|
p_special->Genus.Special->ammo = SPECIAL_AMMO_IN_A_SHOTGUN;
|
|
p_person->Genus.Person->ammo_packs_shotgun = ammo_in_clip;
|
|
}
|
|
|
|
ammo = HAD_TO_CHANGE_CLIP;
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Using the pistol.
|
|
//
|
|
|
|
*sound = SOUND_Range(S_PISTOL_SHOT,S_PISTOL_SHOT_END);
|
|
*time = 140;
|
|
|
|
if (p_person->Genus.Person->Ammo)
|
|
{
|
|
p_person->Genus.Person->Ammo--;
|
|
|
|
//
|
|
// We have ammo.
|
|
//
|
|
|
|
ammo = TRUE;
|
|
*anim = ANIM_PISTOL_SHOOT;
|
|
}
|
|
else
|
|
{
|
|
/* if(p_person->Genus.Person->ammo_packs_pistol)
|
|
{
|
|
p_person->Genus.Person->ammo_packs_pistol--;
|
|
p_person->Genus.Person->Ammo = SPECIAL_AMMO_IN_A_PISTOL;
|
|
ammo = HAD_TO_CHANGE_CLIP;
|
|
}*/
|
|
if(p_person->Genus.Person->ammo_packs_pistol)
|
|
{
|
|
ammo_in_clip=p_person->Genus.Person->ammo_packs_pistol;
|
|
ammo_in_clip-=SPECIAL_AMMO_IN_A_PISTOL;
|
|
if (ammo_in_clip<0)
|
|
{
|
|
p_person->Genus.Person->Ammo = p_person->Genus.Person->ammo_packs_pistol;
|
|
p_person->Genus.Person->ammo_packs_pistol = 0;
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Ammo = SPECIAL_AMMO_IN_A_PISTOL;
|
|
p_person->Genus.Person->ammo_packs_pistol = ammo_in_clip;
|
|
}
|
|
|
|
ammo = HAD_TO_CHANGE_CLIP;
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return ammo;
|
|
}
|
|
|
|
void actually_fire_gun(Thing *p_person)
|
|
{
|
|
WaveParams shot;
|
|
SLONG rico_id;
|
|
// Set up the wave params.
|
|
|
|
shot.Priority = 0;
|
|
shot.Flags = WAVE_CARTESIAN;
|
|
shot.Mode.Cartesian.Scale = (128<<8);
|
|
shot.Mode.Cartesian.X = p_person->WorldPos.X;
|
|
shot.Mode.Cartesian.Y = p_person->WorldPos.Y;
|
|
shot.Mode.Cartesian.Z = p_person->WorldPos.Z;
|
|
|
|
PCOM_oscillate_tympanum(
|
|
PCOM_SOUND_GUNSHOT,
|
|
p_person,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
GAME_FLAGS |= GF_PLAYER_FIRED_GUN;
|
|
if (p_person->Genus.Person->Target)
|
|
timer_bored=0;
|
|
}
|
|
|
|
{
|
|
//
|
|
// A dynamic light muzzle flash that only lasts one frame.
|
|
//
|
|
|
|
UBYTE dlight;
|
|
|
|
dlight = NIGHT_dlight_create(
|
|
(p_person->WorldPos.X >> 8) - (SIN(p_person->Draw.Tweened->Angle) >> 9),
|
|
(p_person->WorldPos.Y >> 8) + 0x60,
|
|
(p_person->WorldPos.Z >> 8) - (COS(p_person->Draw.Tweened->Angle) >> 9),
|
|
100,
|
|
30,
|
|
25,
|
|
5);
|
|
|
|
if (dlight)
|
|
{
|
|
NIGHT_dlight[dlight].flag |= NIGHT_DLIGHT_FLAG_REMOVE;
|
|
}
|
|
}
|
|
|
|
#ifndef BUILD_PSX
|
|
|
|
extern void DIRT_create_brass(SLONG x,SLONG y,SLONG z,SLONG angle);
|
|
|
|
{
|
|
GameCoord vec;
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_LEFT_HAND,
|
|
&vec.X,
|
|
&vec.Y,
|
|
&vec.Z);
|
|
vec.X+=p_person->WorldPos.X>>8;
|
|
vec.Y+=p_person->WorldPos.Y>>8;
|
|
vec.Z+=p_person->WorldPos.Z>>8;
|
|
DIRT_create_brass(vec.X,vec.Y,vec.Z,(p_person->Draw.Tweened->Angle+512)&2047);
|
|
if (p_person->Genus.Person->SpecialUse||PersonIsMIB(p_person))
|
|
{
|
|
Thing* p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
if ((!p_person->Genus.Person->SpecialUse)||(p_special->Genus.Special->SpecialType==SPECIAL_AK47))
|
|
{
|
|
// go OTT with AK...
|
|
DIRT_create_brass(vec.X,vec.Y,vec.Z,(p_person->Draw.Tweened->Angle+512)&2047);
|
|
DIRT_create_brass(vec.X,vec.Y,vec.Z,(p_person->Draw.Tweened->Angle+512)&2047);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
#ifdef PSX
|
|
if (p_person->Genus.Person->PlayerID)
|
|
PSX_SetShock(1,0); // Just shock the fast one
|
|
#endif
|
|
#endif
|
|
#ifdef TARGET_DC
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
switch (p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_AK47:
|
|
Vibrate ( 4.0f, 1.0f, 0.0f );
|
|
break;
|
|
case SPECIAL_SHOTGUN:
|
|
Vibrate ( 6.5f, 1.0f, 0.0f );
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// It's a pistol.
|
|
Vibrate ( 8.0f, 1.0f, 0.0f );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
if (p_person->Genus.Person->Target)
|
|
{
|
|
SLONG damage;
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
GameCoord vec;
|
|
SLONG gun_type;
|
|
/*
|
|
if (p_target->Class == CLASS_PERSON && is_person_ko(p_target))
|
|
{
|
|
return;
|
|
}
|
|
*/
|
|
|
|
if (p_target->Class == CLASS_PERSON && (p_target->Genus.Person->Flags & (FLAG_PERSON_DRIVING|FLAG_PERSON_PASSENGER)))
|
|
{
|
|
//
|
|
// Shoot the car this person is driving.
|
|
//
|
|
|
|
p_person->Genus.Person->Target = p_target->Genus.Person->InCar;
|
|
p_target = TO_THING(p_target->Genus.Person->InCar);
|
|
}
|
|
|
|
damage = get_shoot_damage(p_person, p_target, &gun_type);
|
|
|
|
if (damage)
|
|
{
|
|
//
|
|
// We have hit our target.
|
|
//
|
|
|
|
PYRO_hitspang(p_person, p_target);
|
|
timer_bored=0;
|
|
|
|
if (p_target->Class == CLASS_PERSON )
|
|
{
|
|
if (!p_target->Genus.Person->PlayerID)
|
|
{
|
|
|
|
if (p_target->Genus.Person->Health > 0 && !is_person_ko(p_target))
|
|
{
|
|
SLONG skill = GET_SKILL(p_target);
|
|
|
|
if (PersonIsMIB(p_person))
|
|
{
|
|
//
|
|
// MIB are expert bullet dodgers!
|
|
//
|
|
|
|
skill += 5;
|
|
}
|
|
|
|
//
|
|
// High skill level people can dodge bullets!
|
|
//
|
|
|
|
if (skill >= 7)
|
|
{
|
|
skill -= 5;
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing* p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
if (p_special->Genus.Special->SpecialType==SPECIAL_SHOTGUN)
|
|
{
|
|
skill-=5; // you have to be at least level 10 to dodge a wide shotgun spread, mike.
|
|
}
|
|
}
|
|
|
|
if ((Random() & 0x1f) < skill )
|
|
{
|
|
PCOM_attack_happened(p_target, p_person);
|
|
|
|
set_person_flip(p_target, Random() & 0x1);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
else
|
|
{
|
|
timer_bored=0;
|
|
}
|
|
*/
|
|
// do a lil bloodsplat
|
|
#ifndef PSX
|
|
if(VIOLENCE)
|
|
{
|
|
calc_sub_objects_position(
|
|
p_target,
|
|
p_target->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_LEFT_HAND,
|
|
&vec.X,
|
|
&vec.Y,
|
|
&vec.Z);
|
|
vec.X+=(Random()&0x1f);
|
|
vec.Y+=(Random()&0x1f);
|
|
vec.Z+=(Random()&0x1f);
|
|
vec.X<<=8; vec.Y<<=8; vec.Z<<=8;
|
|
vec.X+=p_target->WorldPos.X;
|
|
vec.Y+=p_target->WorldPos.Y;
|
|
vec.Z+=p_target->WorldPos.Z;
|
|
PARTICLE_Add(vec.X,vec.Y,vec.Z,0,0,0,
|
|
POLY_PAGE_SMOKECLOUD2,2+((Random()&3)<<2),0x7FFF0000,
|
|
PFLAG_SPRITEANI|PFLAG_SPRITELOOP|PFLAG_FADE,10,75,1,20,5);
|
|
}
|
|
#endif
|
|
apply_hit_to_person(
|
|
p_target,
|
|
0, // angle
|
|
gun_type,
|
|
damage,
|
|
p_person,
|
|
NULL); // Fight frame
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// Target someone else once you've killed someone.
|
|
//
|
|
#ifdef PSX
|
|
PSX_SetShock(1,damage+32);
|
|
#endif
|
|
#ifdef TARGET_DC
|
|
// Eh? Why should this vibrate? I've already vibrated from the gunshot -
|
|
// just because you hit or missed the person, or did them more or less
|
|
// damage, doesn't mean you should vibrate as well.
|
|
// Madness.
|
|
//Vibrate ( 5.0f, (float)(damage+32) * 0.01f, 0.0f );
|
|
#endif
|
|
|
|
if (p_target->Genus.Person->Health <= 0)
|
|
{
|
|
p_person->Genus.Person->Target = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (p_target->Class == CLASS_BAT)
|
|
{
|
|
BAT_apply_hit(
|
|
p_target,
|
|
p_person,
|
|
damage);
|
|
}
|
|
else
|
|
if (p_target->Class == CLASS_VEHICLE)
|
|
{
|
|
//
|
|
// Not another full recompile for me!
|
|
//
|
|
|
|
extern void VEH_reduce_health(Thing *p_car, Thing *p_person, SLONG damage);
|
|
|
|
VEH_reduce_health(
|
|
p_target,
|
|
p_person,
|
|
damage);
|
|
|
|
p_target->Genus.Vehicle->Flags |= FLAG_VEH_SHOT_AT; // Tell the vehicle it is being attacked.
|
|
}
|
|
else
|
|
if (p_target->Class == CLASS_SPECIAL)
|
|
{
|
|
//
|
|
// This must be a mine!
|
|
//
|
|
|
|
void special_activate_mine(Thing *p_mine);
|
|
|
|
special_activate_mine(p_target);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(p_target->Class == CLASS_BARREL);
|
|
|
|
BARREL_shoot(
|
|
p_target,
|
|
p_person);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Miss!
|
|
//
|
|
|
|
shot.Mode.Cartesian.X -= (SIN(p_person->Draw.Tweened->Angle)*1024)>>8;
|
|
shot.Mode.Cartesian.Z -= (COS(p_person->Draw.Tweened->Angle)*1024)>>8;
|
|
|
|
rico_id = ((Random()*(S_RICOCHET_END-S_RICOCHET_START))>>16)+S_RICOCHET_START;
|
|
|
|
MFX_play_xyz(0,rico_id,0,shot.Mode.Cartesian.X,shot.Mode.Cartesian.Y,shot.Mode.Cartesian.Z);
|
|
|
|
//
|
|
// Where did the bullet hit if it didn't hit the target?
|
|
//
|
|
|
|
SLONG hitx;
|
|
SLONG hity;
|
|
SLONG hitz;
|
|
|
|
SLONG b_index = THING_find_nearest(
|
|
p_target->WorldPos.X >> 8,
|
|
p_target->WorldPos.Y >> 8,
|
|
p_target->WorldPos.Z >> 8,
|
|
0xa0,
|
|
1 << CLASS_BARREL);
|
|
|
|
if (b_index)
|
|
{
|
|
Thing *p_barrel = TO_THING(b_index);
|
|
|
|
hitx = p_barrel->WorldPos.X >> 8;
|
|
hity = p_barrel->WorldPos.Y >> 8;
|
|
hitz = p_barrel->WorldPos.Z >> 8;
|
|
|
|
BARREL_shoot(
|
|
p_barrel,
|
|
p_person);
|
|
}
|
|
else
|
|
{
|
|
hitx = p_target->WorldPos.X + (Random() & 0x1fff) - 0xfff;
|
|
hitz = p_target->WorldPos.Z + (Random() & 0x1fff) - 0xfff;
|
|
|
|
hity = PAP_calc_map_height_at(hitx >> 8, hitz >> 8) + 0x1000;
|
|
}
|
|
|
|
PYRO_hitspang(
|
|
p_person,
|
|
hitx,
|
|
hity,
|
|
hitz);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Shoot a coke can?
|
|
//
|
|
|
|
if (DIRT_shoot(p_person))
|
|
{
|
|
shot.Mode.Cartesian.X -= (SIN(p_person->Draw.Tweened->Angle)*1024)>>8;
|
|
shot.Mode.Cartesian.Z -= (COS(p_person->Draw.Tweened->Angle)*1024)>>8;
|
|
|
|
// PlayWave(THING_NUMBER(p_person),S_PISTOL_SHOT,WAVE_PLAY_QUEUE,&shot);
|
|
// play_quick_wave_old(&shot,S_PISTOL_SHOT,0,0);
|
|
MFX_play_xyz(0,S_PISTOL_SHOT,0,shot.Mode.Cartesian.X,shot.Mode.Cartesian.Y,shot.Mode.Cartesian.Z);
|
|
|
|
}
|
|
else
|
|
{
|
|
shot.Mode.Cartesian.X -= (SIN(p_person->Draw.Tweened->Angle)*1024)>>8;
|
|
shot.Mode.Cartesian.Z -= (COS(p_person->Draw.Tweened->Angle)*1024)>>8;
|
|
|
|
rico_id = ((Random()*(S_RICOCHET_END-S_RICOCHET_START))>>16)+S_RICOCHET_START;
|
|
// PlayWave(THING_NUMBER(p_person),rico_id,WAVE_PLAY_QUEUE,&shot);
|
|
MFX_play_xyz(0,rico_id,0,shot.Mode.Cartesian.X,shot.Mode.Cartesian.Y,shot.Mode.Cartesian.Z);
|
|
// play_quick_wave_old(&shot,rico_id,0,0);
|
|
|
|
//
|
|
// Find where the bullet hit...
|
|
//
|
|
|
|
{
|
|
SLONG endx = p_person->WorldPos.X - (SIN(p_person->Draw.Tweened->Angle) << 2) >> 8;
|
|
SLONG endy = p_person->WorldPos.Y + 0x6000 >> 8;
|
|
SLONG endz = p_person->WorldPos.Z - (COS(p_person->Draw.Tweened->Angle) << 2) >> 8;
|
|
|
|
if (there_is_a_los(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
endx,
|
|
endy,
|
|
endz,
|
|
0))
|
|
{
|
|
PYRO_hitspang(
|
|
p_person,
|
|
endx << 8,
|
|
endy << 8,
|
|
endz << 8);
|
|
}
|
|
else
|
|
{
|
|
PYRO_hitspang(
|
|
p_person,
|
|
los_failure_x << 8,
|
|
los_failure_y << 8,
|
|
los_failure_z << 8);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void set_person_running_shoot(Thing *p_person)
|
|
{
|
|
SLONG ammo,sound,anim,time;
|
|
|
|
if (p_person->Genus.Person->Timer1)
|
|
{
|
|
//
|
|
// Too little time since the last shot.
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
ammo = shoot_get_ammo_sound_anim_time(p_person,&sound,&anim,&time);
|
|
|
|
if (ammo == NOT_A_GUN_YOU_SHOOT)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!ammo || ammo == HAD_TO_CHANGE_CLIP)
|
|
{
|
|
MFX_play_thing(THING_NUMBER(p_person),S_PISTOL_DRY,MFX_REPLACE,p_person);
|
|
return;
|
|
}
|
|
|
|
MFX_play_thing(THING_NUMBER(p_person),sound,MFX_REPLACE,p_person);
|
|
|
|
actually_fire_gun(p_person);
|
|
|
|
//
|
|
// Make sure this person can't fire the gun again for a while...
|
|
//
|
|
|
|
p_person->Genus.Person->Timer1 = time;
|
|
}
|
|
|
|
|
|
//
|
|
// Returns the best type of special a person has that's got ammo.
|
|
//
|
|
|
|
SLONG get_persons_best_weapon_with_ammo(Thing *p_person)
|
|
{
|
|
Thing *p_special;
|
|
|
|
//
|
|
// The weapon order is:
|
|
//
|
|
// AK47
|
|
// shotgun
|
|
// gun
|
|
// baseball bat
|
|
// knife
|
|
//
|
|
|
|
static UBYTE weapon_order[5] =
|
|
{
|
|
SPECIAL_AK47,
|
|
SPECIAL_SHOTGUN,
|
|
SPECIAL_GUN,
|
|
SPECIAL_BASEBALLBAT,
|
|
SPECIAL_KNIFE
|
|
};
|
|
|
|
SLONG i;
|
|
|
|
for (i = 0; i < 5; i++)
|
|
{
|
|
if (i == 2)
|
|
{
|
|
if (p_person->Flags & FLAGS_HAS_GUN)
|
|
{
|
|
if (p_person->Genus.Person->Ammo)
|
|
{
|
|
return SPECIAL_GUN;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p_special = person_has_special(p_person, weapon_order[i]))
|
|
{
|
|
if (i < 2)
|
|
{
|
|
if (p_special->Genus.Special->ammo)
|
|
{
|
|
return weapon_order[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return weapon_order[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return SPECIAL_NONE;
|
|
}
|
|
|
|
|
|
//
|
|
// Returns TRUE if you shouldn't hit this person due to
|
|
// a cutscene playing.
|
|
//
|
|
|
|
SLONG dont_hurt_target_during_cutscene(Thing *p_person, Thing *p_target)
|
|
{
|
|
if (!p_person->Genus.Person->PlayerID)
|
|
{
|
|
if (p_target->Class == CLASS_PERSON)
|
|
{
|
|
SLONG dont_shoot_in_a_cutscene = FALSE;
|
|
|
|
if (p_target->Genus.Person->PlayerID)
|
|
{
|
|
dont_shoot_in_a_cutscene = TRUE;
|
|
}
|
|
else
|
|
if (p_target->Genus.Person->pcom_move == PCOM_MOVE_FOLLOW)
|
|
{
|
|
//
|
|
// Dont shoot people in a cutscene who are following the player.
|
|
//
|
|
|
|
UWORD i_follow = EWAY_get_person(p_person->Genus.Person->pcom_move_follow);
|
|
|
|
if (i_follow)
|
|
{
|
|
Thing *p_follow = TO_THING(i_follow);
|
|
|
|
if (p_follow->Class == CLASS_PERSON && p_follow->Genus.Person->PlayerID)
|
|
{
|
|
dont_shoot_in_a_cutscene = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dont_shoot_in_a_cutscene && EWAY_stop_player_moving())
|
|
{
|
|
//
|
|
// Don't shoot.
|
|
//
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void set_person_shoot(Thing *p_person,UWORD shoot_target)
|
|
{
|
|
SLONG dx,dz;
|
|
SLONG anim = ANIM_PISTOL_SHOOT;
|
|
SLONG ammo = FALSE;
|
|
SLONG sound;
|
|
SLONG time;
|
|
|
|
if (p_person->State == STATE_CARRY)
|
|
{
|
|
//
|
|
// Can't shoot while carrying someone.
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
if(might_i_be_a_villain(p_person))
|
|
{
|
|
//
|
|
// arrest anyone who might be a villain
|
|
//
|
|
PCOM_call_cop_to_arrest_me(p_person,1);
|
|
}
|
|
|
|
if(p_person->SubState==SUB_STATE_RUNNING)
|
|
{
|
|
set_person_running_shoot(p_person);
|
|
return;
|
|
}
|
|
|
|
p_person->Genus.Person->Timer1=0; // used for ak47 to limit continuos fire
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// For players...
|
|
//
|
|
|
|
if (p_person->Genus.Person->Target)
|
|
{
|
|
Thing *p_target;
|
|
|
|
p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
//
|
|
// Players twist their body towards their target- but because they
|
|
// can't shoot and twist at the same time, turn them to face their
|
|
// target.
|
|
//
|
|
|
|
// set_face_thing(p_person, TO_THING(p_person->Genus.Person->Target));
|
|
|
|
if (p_target->Class == CLASS_PERSON)
|
|
{
|
|
//
|
|
// You get punished for killing innocents nowadays...
|
|
//
|
|
|
|
// PANEL_new_help_message("I, Mark Adami, think you should be able to shoot unarmed people.");
|
|
if(p_person->Genus.Person->PersonType==PERSON_DARCI)
|
|
{
|
|
if(p_target->Draw.Tweened->CurrentAnim==ANIM_HANDS_UP||p_target->Draw.Tweened->CurrentAnim==ANIM_HANDS_UP_LOOP)
|
|
{
|
|
// PANEL_new_text(p_person,8000,"Get Down.");
|
|
PANEL_new_text(p_person,8000,XLAT_str(X_GET_DOWN));
|
|
set_person_dead(p_target,p_person,PERSON_DEATH_TYPE_GET_DOWN,0,0);
|
|
|
|
//
|
|
// Look for a new target now...
|
|
//
|
|
|
|
p_person->Genus.Person->Target = NULL;
|
|
|
|
// set_person_get_down(p_target);
|
|
return; //leave this here its good for you.
|
|
}
|
|
if(p_target->Genus.Person->PersonType==PERSON_COP && !(p_target->Genus.Person->Flags2&FLAG2_PERSON_GUILTY))
|
|
{
|
|
|
|
// PANEL_new_text(p_person,8000,"I can't shoot a Cop.");
|
|
PANEL_new_text(p_person,8000,XLAT_str(X_CANT_SHOOT_COP));
|
|
|
|
return; //leave this here its good for you.
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// For non-player characters. If the player is in a cut scene then
|
|
// it is a bit unfair to shoot them!
|
|
//
|
|
|
|
if (p_person->Genus.Person->Target)
|
|
{
|
|
Thing *p_target;
|
|
|
|
p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
if (p_target->Class == CLASS_VEHICLE)
|
|
{
|
|
if (p_target->State == STATE_DEAD)
|
|
{
|
|
p_person->Genus.Person->Target = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dont_hurt_target_during_cutscene(p_person, p_target))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ammo=shoot_get_ammo_sound_anim_time(p_person,&sound,&anim,&time);
|
|
|
|
if (ammo == NOT_A_GUN_YOU_SHOOT)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!ammo || ammo == HAD_TO_CHANGE_CLIP)
|
|
{
|
|
MFX_play_thing(THING_NUMBER(p_person),S_PISTOL_DRY,MFX_REPLACE,p_person);
|
|
|
|
if (p_person->Genus.Person->PlayerID && ammo != HAD_TO_CHANGE_CLIP)
|
|
{
|
|
//
|
|
// Change Darci's weapon.
|
|
//
|
|
|
|
SLONG special = get_persons_best_weapon_with_ammo(p_person);
|
|
|
|
if (special)
|
|
{
|
|
if (special == SPECIAL_GUN)
|
|
{
|
|
set_person_draw_gun(p_person);
|
|
}
|
|
else
|
|
{
|
|
set_person_draw_item(p_person, special);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
set_person_item_away(p_person);
|
|
}
|
|
else
|
|
{
|
|
set_person_gun_away(p_person);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
set_anim(p_person,anim);
|
|
p_person->Genus.Person->Action=ACTION_SHOOT;
|
|
|
|
set_generic_person_state_function(p_person,STATE_GUN);
|
|
|
|
p_person->SubState=SUB_STATE_SHOOT_GUN;
|
|
// p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
p_person->Genus.Person->Flags|=(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
p_person->Draw.Tweened->Flags|=DT_FLAG_GUNFLASH;
|
|
|
|
{
|
|
|
|
|
|
// ideally the 0 in the above line would be fixed up on some kind of
|
|
// person-by-person basis. ask me about it later. :P
|
|
// hey look! it got fixed up on a person-by-person basis! ;)
|
|
|
|
if (!shoot_target || p_person->Genus.Person->Target==0)
|
|
{
|
|
//
|
|
// Find someone to shoot
|
|
//
|
|
|
|
p_person->Genus.Person->Target = find_target_new(p_person);
|
|
|
|
//
|
|
// check it's not a cut scene again
|
|
//
|
|
if (p_person->Genus.Person->Target)
|
|
{
|
|
Thing *p_target;
|
|
|
|
p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
|
|
set_face_thing(p_person, p_target);
|
|
|
|
if (p_target->Class == CLASS_PERSON)
|
|
{
|
|
//
|
|
// You get punished for killing innocents nowadays...
|
|
//
|
|
|
|
if(p_person->Genus.Person->PersonType==PERSON_DARCI)
|
|
{
|
|
if(p_target->Draw.Tweened->CurrentAnim==ANIM_HANDS_UP||p_target->Draw.Tweened->CurrentAnim==ANIM_HANDS_UP_LOOP)
|
|
{
|
|
PANEL_new_text(p_person,8000,XLAT_str(X_GET_DOWN));
|
|
// PANEL_new_text(p_person,8000,"Get Down.");
|
|
set_person_dead(p_target,p_person,PERSON_DEATH_TYPE_GET_DOWN,0,0);
|
|
// set_person_get_down(p_target);
|
|
return; //leave this here its good for you.
|
|
}
|
|
|
|
if (p_target->Draw.Tweened->CurrentAnim == ANIM_HANDS_UP_LIE)
|
|
{
|
|
//
|
|
// Can't shoot civs while they are 'getting down'.
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
if(p_target->Genus.Person->PersonType==PERSON_COP && !(p_target->Genus.Person->Flags2&FLAG2_PERSON_GUILTY))
|
|
{
|
|
PANEL_new_text(p_person,8000,XLAT_str(X_CANT_SHOOT_COP));
|
|
return; //leave this here its good for you.
|
|
|
|
}
|
|
}
|
|
/*
|
|
if(p_target->Draw.Tweened->CurrentAnim==ANIM_HANDS_UP)
|
|
{
|
|
PANEL_new_text(p_person,8000,"I can't shoot an Unarmed Person.");
|
|
return; //leave this here its good for you.
|
|
}
|
|
if(p_target->Genus.Person->PersonType==PERSON_COP)
|
|
{
|
|
PANEL_new_text(p_person,8000,"I can't shoot a Cop.");
|
|
return; //leave this here its good for you.
|
|
|
|
}
|
|
*/
|
|
|
|
if (p_target->Genus.Person->PlayerID)
|
|
{
|
|
if (EWAY_stop_player_moving())
|
|
{
|
|
//
|
|
// Don't shoot.
|
|
//
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
MFX_play_thing(THING_NUMBER(p_person),sound,MFX_REPLACE,p_person);
|
|
|
|
ASSERT(p_person->Genus.Person->Target != THING_NUMBER(p_person));
|
|
// ASSERT(TO_THING(p_person->Genus.Person->Target)->Class==CLASS_PERSON);
|
|
|
|
//
|
|
// Guards can hear gunshots.
|
|
//
|
|
|
|
|
|
actually_fire_gun(p_person);
|
|
}
|
|
}
|
|
|
|
#ifndef PSX
|
|
void set_person_grapple_windup(Thing *p_person)
|
|
{
|
|
//
|
|
// Make sure she has the grappling hook.
|
|
//
|
|
|
|
ASSERT(p_person->Genus.Person->Flags & FLAG_PERSON_GRAPPLING);
|
|
|
|
//
|
|
// Set the animation.
|
|
//
|
|
|
|
set_anim(p_person, ANIM_GRAPPLING_HOOK_WINDUP);
|
|
|
|
//
|
|
// Set the state.
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_GRAPPLING);
|
|
|
|
p_person->SubState = SUB_STATE_GRAPPLING_WINDUP;
|
|
}
|
|
|
|
|
|
void set_person_grappling_hook_release(Thing *p_person)
|
|
{
|
|
//
|
|
// Make sure she has the grappling hook.
|
|
//
|
|
|
|
ASSERT(p_person->Genus.Person->Flags & FLAG_PERSON_GRAPPLING);
|
|
|
|
//
|
|
// Set the animation.
|
|
//
|
|
|
|
set_anim(p_person, ANIM_GRAPPLING_HOOK_RELEASE);
|
|
|
|
//
|
|
// Set the state.
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_GRAPPLING);
|
|
|
|
p_person->SubState = SUB_STATE_GRAPPLING_RELEASE;
|
|
}
|
|
#endif
|
|
//
|
|
// Returns SPECIAL_TYPE if the given person is holding a gun.
|
|
//
|
|
|
|
SLONG person_has_gun_out(Thing *p_person)
|
|
{
|
|
if (p_person->Genus.Person->Flags&FLAG_PERSON_GUN_OUT)
|
|
{
|
|
return(SPECIAL_GUN);
|
|
}
|
|
|
|
if (!p_person->Genus.Person->SpecialUse)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
|
|
if (p_special->Genus.Special->SpecialType == SPECIAL_SHOTGUN ||
|
|
p_special->Genus.Special->SpecialType == SPECIAL_AK47)
|
|
{
|
|
return(p_special->Genus.Special->SpecialType);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void drop_current_gun(Thing *p_person,SLONG change_anim)
|
|
{
|
|
SLONG gx;
|
|
SLONG gy;
|
|
SLONG gz;
|
|
|
|
Thing *p_special;
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
Thing *p_gun;
|
|
|
|
//
|
|
// Create a gun on the ground.
|
|
//
|
|
|
|
find_nice_place_near_person(
|
|
p_person,
|
|
&gx,
|
|
&gy,
|
|
&gz);
|
|
|
|
p_gun = alloc_special(
|
|
SPECIAL_GUN,
|
|
SPECIAL_SUBSTATE_NONE,
|
|
gx,
|
|
gy,
|
|
gz,
|
|
NULL);
|
|
|
|
if (p_gun)
|
|
{
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
p_gun->Genus.Special->ammo = p_person->Genus.Person->Ammo;
|
|
}
|
|
else
|
|
{
|
|
p_gun->Genus.Special->ammo = (Random() & 0x3) + 3;
|
|
}
|
|
}
|
|
|
|
//
|
|
// p_person doesn't have the gun any more.
|
|
//
|
|
|
|
p_person->Draw.Tweened->PersonID&= ~0xe0;
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_GUN_OUT;
|
|
p_person->Flags &= ~FLAGS_HAS_GUN;
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
//
|
|
// Drop the special that p_person is using.
|
|
//
|
|
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
special_drop(p_special, p_person);
|
|
|
|
//
|
|
// Not using anything any more.
|
|
//
|
|
|
|
p_person->Genus.Person->SpecialUse = NULL;
|
|
p_person->Draw.Tweened->PersonID&= ~0xe0;
|
|
//p_person->Draw.Tweened->PersonID = 0;
|
|
|
|
if(change_anim)
|
|
set_person_idle(p_person);
|
|
}
|
|
}
|
|
|
|
void drop_all_items(Thing *p_person, UBYTE is_being_searched)
|
|
{
|
|
SLONG gx;
|
|
SLONG gy;
|
|
SLONG gz;
|
|
UBYTE found_something=0;
|
|
|
|
//
|
|
// If he has a gun...
|
|
//
|
|
|
|
if (p_person->Flags & FLAGS_HAS_GUN)
|
|
{
|
|
find_nice_place_near_person(
|
|
p_person,
|
|
&gx,
|
|
&gy,
|
|
&gz);
|
|
|
|
{
|
|
Thing *p_gun = alloc_special(
|
|
SPECIAL_GUN,
|
|
SPECIAL_SUBSTATE_NONE,
|
|
gx,
|
|
gy,
|
|
gz,
|
|
NULL);
|
|
|
|
if (p_gun)
|
|
{
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
p_gun->Genus.Special->ammo = p_person->Genus.Person->Ammo;
|
|
}
|
|
else
|
|
{
|
|
p_gun->Genus.Special->ammo = (Random() & 0x3) + 3;
|
|
}
|
|
found_something=1;
|
|
}
|
|
}
|
|
|
|
p_person->Flags &= ~FLAGS_HAS_GUN;
|
|
}
|
|
|
|
//
|
|
// Make the person drop all the specials he is carrying.
|
|
//
|
|
|
|
while(p_person->Genus.Person->SpecialList)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialList);
|
|
|
|
if (p_person->Genus.Person->drop == p_special->Genus.Special->SpecialType)
|
|
{
|
|
//
|
|
// Already dropping his bounty...
|
|
//
|
|
|
|
p_person->Genus.Person->drop = NULL;
|
|
}
|
|
|
|
special_drop(p_special, p_person);
|
|
found_something=1;
|
|
}
|
|
|
|
//
|
|
// Make the person drop his bounty.
|
|
//
|
|
|
|
if (p_person->Genus.Person->drop)
|
|
{
|
|
find_nice_place_near_person(
|
|
p_person,
|
|
&gx,
|
|
&gy,
|
|
&gz);
|
|
|
|
alloc_special(
|
|
p_person->Genus.Person->drop,
|
|
SPECIAL_SUBSTATE_NONE,
|
|
gx,
|
|
gy,
|
|
gz,
|
|
NULL);
|
|
|
|
p_person->Genus.Person->drop = NULL;
|
|
found_something=1;
|
|
}
|
|
if (is_being_searched&&found_something) MFX_play_ambient(THING_NUMBER(p_person),S_ITEM_REVEALED,0);
|
|
|
|
}
|
|
|
|
|
|
void set_person_idle_uncroutch(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
p_person->Genus.Person->Action=ACTION_IDLE;
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C;
|
|
p_person->SubState = SUB_STATE_IDLE_UNCROUCH;
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
anim=ANIM_UNCROUTCH_PISTOL;
|
|
}
|
|
else
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
anim=ANIM_UNCROUTCH_AK;
|
|
}
|
|
else
|
|
{
|
|
anim=ANIM_CROUTCH_GETUP;
|
|
}
|
|
|
|
set_anim(p_person, anim);
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_person_turn_to_hug_wall(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
anim=ANIM_PRESS_WALL_TURN_PISTOL;
|
|
}
|
|
else
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
anim=ANIM_PRESS_WALL_TURN_AK;
|
|
}
|
|
else
|
|
{
|
|
anim=ANIM_PRESS_WALL_TURN;
|
|
}
|
|
set_generic_person_state_function(p_person,STATE_HUG_WALL);
|
|
p_person->SubState=SUB_STATE_HUG_WALL_TURN;
|
|
set_anim(p_person,anim);
|
|
p_person->Genus.Person->Action=ACTION_HUG_WALL;
|
|
}
|
|
|
|
void set_person_hug_wall_dir(Thing *p_person,SLONG dir)
|
|
{
|
|
SLONG gun;
|
|
SLONG anim;
|
|
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
gun=2;
|
|
else
|
|
gun=person_holding_2handed(p_person);
|
|
if(dir==1)
|
|
{
|
|
//
|
|
//left
|
|
//
|
|
if(gun==2)
|
|
anim=ANIM_PRESS_WALL_SIDLE_R_PISTOL;
|
|
else
|
|
if(gun==1)
|
|
anim=ANIM_PRESS_WALL_SIDLE_R_AK;
|
|
else
|
|
anim=ANIM_PRESS_WALL_SIDLE_R;
|
|
|
|
set_anim(p_person,anim);
|
|
p_person->SubState=SUB_STATE_HUG_WALL_STEP_LEFT;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//right
|
|
//
|
|
if(gun==2)
|
|
anim=ANIM_PRESS_WALL_SIDLE_L_PISTOL;
|
|
else
|
|
if(gun==1)
|
|
anim=ANIM_PRESS_WALL_SIDLE_L_AK;
|
|
else
|
|
anim=ANIM_PRESS_WALL_SIDLE_L;
|
|
|
|
set_anim(p_person,anim);
|
|
p_person->SubState=SUB_STATE_HUG_WALL_STEP_RIGHT;
|
|
|
|
}
|
|
|
|
}
|
|
void set_person_hug_wall_look(Thing *p_person,SLONG dir)
|
|
{
|
|
SLONG gun;
|
|
SLONG anim;
|
|
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
p_person->Genus.Person->InsideRoom=0;
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
gun=2;
|
|
else
|
|
gun=person_holding_2handed(p_person);
|
|
if(dir==1)
|
|
{
|
|
//
|
|
//left
|
|
//
|
|
if(gun==2)
|
|
anim=ANIM_PRESS_WALL_LOOK_L_PISTOL;
|
|
else
|
|
if(gun==1)
|
|
anim=ANIM_PRESS_WALL_LOOK_L_AK;
|
|
else
|
|
anim=ANIM_PRESS_WALL_LOOK_L;
|
|
|
|
set_anim(p_person,anim);
|
|
p_person->SubState=SUB_STATE_HUG_WALL_LOOK_L;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//right
|
|
//
|
|
if(gun==2)
|
|
anim=ANIM_PRESS_WALL_LOOK_R_PISTOL;
|
|
else
|
|
if(gun==1)
|
|
anim=ANIM_PRESS_WALL_LOOK_R_AK;
|
|
else
|
|
anim=ANIM_PRESS_WALL_LOOK_R;
|
|
|
|
set_anim(p_person,anim);
|
|
p_person->SubState=SUB_STATE_HUG_WALL_LOOK_R;
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void set_person_idle(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_KO;
|
|
|
|
if(check_on_slippy_slope(p_person))
|
|
return;
|
|
|
|
|
|
if(p_person->Genus.Person->Flags2&FLAG2_PERSON_CARRYING)
|
|
{
|
|
set_person_stand_carry(p_person);
|
|
return;
|
|
}
|
|
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
if (p_person->Genus.Person->PlayerID && !person_has_gun_out(p_person))
|
|
{
|
|
//
|
|
// You are a player and you're not in fight mode.
|
|
//
|
|
|
|
Thing *p_attacker = is_person_under_attack_low_level(p_person, FALSE, 0x200);
|
|
|
|
if (p_attacker)
|
|
{
|
|
SLONG anim;
|
|
|
|
//
|
|
// You are under attack by someone.
|
|
//
|
|
|
|
ASSERT(p_attacker->Class==CLASS_PERSON);
|
|
|
|
p_person->Genus.Person->Target = THING_NUMBER(p_attacker);
|
|
person_enter_fight_mode(p_person); //for fuck's sake get in fight mode
|
|
set_person_fight_idle(p_person);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Target = 0;
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
p_person->Genus.Person->Agression=0;
|
|
}
|
|
GAME_FLAGS&=~GF_SIDE_ON_COMBAT;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (p_person->Genus.Person->Mode != PERSON_MODE_FIGHT)
|
|
|
|
{
|
|
if(continue_moveing(p_person))
|
|
{
|
|
set_person_running(p_person);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
p_person->SubState = 0;
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_HELPLESS;
|
|
// p_person->Genus.Person->Target = NULL;
|
|
|
|
#ifndef PSX
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GRAPPLING)
|
|
{
|
|
set_person_grapple_windup(p_person);
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
if (person_has_gun_out(p_person))
|
|
{
|
|
set_person_aim(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
p_person->Genus.Person->Timer1=(Random()&0x1ff)+400;
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
p_person->Genus.Person->Action=ACTION_IDLE;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
p_person->Velocity=0;
|
|
|
|
//
|
|
// What animation should we use?
|
|
//
|
|
|
|
set_anim_idle(p_person);
|
|
/*
|
|
if (p_person->Genus.Person->Mode == PERSON_MODE_FIGHT)
|
|
{
|
|
anim=find_idle_fight_stance(p_person);
|
|
|
|
}
|
|
else
|
|
{
|
|
if(person_holding_2handed(p_person) && p_person->Genus.Person->PersonType!=PERSON_ROPER)
|
|
anim=ANIM_SHOTGUN_IDLE;
|
|
else
|
|
anim = ANIM_STAND_READY;
|
|
}
|
|
set_anim(p_person,anim);
|
|
*/
|
|
|
|
/*
|
|
if(p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special;
|
|
|
|
//
|
|
// This person might be using the base ball bat. This weapon has
|
|
// its own special idle stance.
|
|
//
|
|
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
switch(p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_BASEBALLBAT:
|
|
anim = ANIM_BAT_IDLE;
|
|
break;
|
|
case SPECIAL_SHOTGUN:
|
|
case SPECIAL_AK47:
|
|
anim = ANIM_SHOTGUN_STAND;
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
// queue_anim(p_person,anim);
|
|
/*
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_LOCK_ANIM_CHANGE)
|
|
{
|
|
locked_anim_change(p_person,0,ANIM_STAND_READY);
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_LOCK_ANIM_CHANGE;
|
|
}
|
|
else
|
|
{
|
|
p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_STAND_HIP];
|
|
p_person->Draw.Tweened->CurrentAnim = ANIM_STAND_HIP;
|
|
}
|
|
*/
|
|
set_person_sidle(p_person);
|
|
|
|
}
|
|
|
|
|
|
void set_person_locked_idle_ready(Thing *p_person)
|
|
{
|
|
SLONG anim=ANIM_STAND_READY;
|
|
|
|
if(p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special;
|
|
|
|
//
|
|
// This person might be using the base ball bat. This weapon has
|
|
// its own special idle stance.
|
|
//
|
|
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
switch(p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_GUN:
|
|
anim = ANIM_PISTOL_AIM_AHEAD;
|
|
break;
|
|
|
|
case SPECIAL_BASEBALLBAT:
|
|
anim = ANIM_BAT_IDLE;
|
|
break;
|
|
case SPECIAL_SHOTGUN:
|
|
case SPECIAL_AK47:
|
|
anim = ANIM_SHOTGUN_STAND;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
p_person->SubState=0;
|
|
#ifndef PSX
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GRAPPLING)
|
|
{
|
|
set_person_grapple_windup(p_person);
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
p_person->Genus.Person->Timer1=(Random()&0x1ff)+400;
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_GUN_OUT)
|
|
{
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
camera_shoot();
|
|
}
|
|
|
|
|
|
locked_anim_change(p_person,0,anim);
|
|
set_person_aim(p_person);
|
|
/*
|
|
p_person->Genus.Person->Action=ACTION_AIM_GUN;
|
|
set_generic_person_state_function(p_person,STATE_GUN);
|
|
p_person->SubState=SUB_STATE_AIM_GUN;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
p_person->Genus.Person->Flags|=(FLAG_PERSON_NON_INT_C);
|
|
*/
|
|
return;
|
|
}
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
camera_normal();
|
|
}
|
|
|
|
|
|
|
|
|
|
p_person->SubState = 0;
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
p_person->SubState=0;
|
|
|
|
set_locked_anim(p_person,anim,0);
|
|
|
|
/*
|
|
locked_anim_change(p_person,0,anim);
|
|
p_person->Draw.Tweened->AnimTween=0;
|
|
p_person->Draw.Tweened->CurrentAnim = ANIM_STAND_READY;
|
|
*/
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_IDLE;//fight_idle
|
|
// p_person->WorldPos.Y = calc_height_at(p_person->WorldPos.X,p_person->WorldPos.Z);
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
if (person_has_gun_out(p_person))
|
|
{
|
|
set_person_aim(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
set_person_sidle(p_person);
|
|
|
|
}
|
|
|
|
//
|
|
// Check if back against a wall, for sneak along mode
|
|
//
|
|
|
|
SLONG set_person_sidle(struct Thing *p_person)
|
|
{
|
|
SLONG dx,dz;
|
|
SLONG index,facet;
|
|
SLONG dist;
|
|
SLONG px,pz,mx,mz;
|
|
SLONG angle;
|
|
SLONG ret_x,ret_z;
|
|
SLONG mdx,mdz;
|
|
return(0);
|
|
/*
|
|
|
|
px=p_person->WorldPos.X>>8;
|
|
pz=p_person->WorldPos.Z>>8;
|
|
|
|
mx=px>>PAP_SHIFT_LO;
|
|
mz=pz>>PAP_SHIFT_LO;
|
|
|
|
for(mdx=-1;mdx<=1;mdx++)
|
|
for(mdz=-1;mdz<=1;mdz++)
|
|
{
|
|
SLONG mpx,mpz;
|
|
SLONG exit=0;
|
|
|
|
mpx=(mdx*80+px)>>PAP_SHIFT_LO;
|
|
mpz=(mdz*80+pz)>>PAP_SHIFT_LO;
|
|
|
|
if(mpx>=0 && mpx<PAP_SIZE_LO && mpz>=0 && mpz<PAP_SIZE_LO)
|
|
if((mdx==0&&mdz==0)||(mpx!=mx||mpz!=mz))
|
|
{
|
|
index=PAP_2LO(mpx,mpz).ColVectHead;
|
|
|
|
if(index)
|
|
while(!exit)
|
|
{
|
|
struct DFacet *p_facet;
|
|
facet=facet_links[index];
|
|
if(facet<0)
|
|
{
|
|
facet=-facet;
|
|
exit=1;
|
|
|
|
}
|
|
|
|
p_facet=&dfacets[facet];
|
|
|
|
SLONG nearest_point_on_line_and_dist( SLONG x1, SLONG z1, SLONG x2, SLONG z2, SLONG a, SLONG b,SLONG *ret_x,SLONG *ret_z);
|
|
|
|
if(p_facet->FacetType==STOREY_TYPE_NORMAL)
|
|
{
|
|
dist = nearest_point_on_line_and_dist(
|
|
p_facet->x[0] << 8, p_facet->z[0] << 8,
|
|
p_facet->x[1] << 8, p_facet->z[1] << 8,
|
|
px, pz,
|
|
&ret_x,
|
|
&ret_z);
|
|
|
|
if(dist>0&&dist<40)
|
|
{
|
|
SLONG dx,dz;
|
|
|
|
dx=(px)-ret_x;
|
|
dz=(pz)-ret_z;
|
|
|
|
angle=calc_angle(dx,dz);
|
|
angle-=p_person->Draw.Tweened->Angle;
|
|
|
|
if((angle>-1024-100 && angle<-1024+100)|| (angle>1024-100 && angle<1024+100))
|
|
{
|
|
//
|
|
// valid wall to sidle along
|
|
//
|
|
// p_person->Genus.Person->Action=ACTION_SIDE_STEP;
|
|
p_person->SubState=SUB_STATE_SIDLE;
|
|
p_person->Draw.Tweened->Angle=(calc_angle(dx,dz)+1024)&2047;
|
|
return(1);
|
|
}
|
|
}
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
return(0);
|
|
*/
|
|
|
|
}
|
|
|
|
/*
|
|
void set_person_idle_ready(Thing *p_person)
|
|
{
|
|
p_person->SubState=0;
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GRAPPLING)
|
|
{
|
|
set_person_grapple_windup(p_person);
|
|
|
|
return;
|
|
}
|
|
p_person->Genus.Person->Timer1=(Random()&0xff)+100;
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_GUN_OUT)
|
|
{
|
|
set_person_aim(p_person);
|
|
return;
|
|
}
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
p_person->SubState=0;
|
|
|
|
// queue_anim(p_person,ANIM_STAND_READY);
|
|
set_anim(p_person,ANIM_STAND_READY);
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_IDLE;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
set_person_sidle(p_person);
|
|
}
|
|
*/
|
|
|
|
//
|
|
// See if this location contains a viable platform for a fott or a hand or anything
|
|
// has an offset from the player, that is rotated by the players angle
|
|
//
|
|
#ifdef UNUSED
|
|
SLONG foot_hold_available(Thing *p_person,SLONG dx,SLONG dy,SLONG dz)
|
|
{
|
|
SLONG rdx,rdz;
|
|
SLONG angle;
|
|
|
|
SLONG px,py,pz,ret_y,face;
|
|
|
|
angle=p_person->Draw.Tweened->Angle;
|
|
|
|
rdx=(dx*COS(angle)-dz*SIN(angle))>>16;
|
|
rdz=(dx*SIN(angle)+dz*COS(angle))>>16;
|
|
|
|
px=(p_person->WorldPos.X>>8)+rdx;
|
|
py=(p_person->WorldPos.Y>>8);
|
|
pz=(p_person->WorldPos.Z>>8)+rdz;
|
|
|
|
face=find_face_for_this_pos(px,py,pz,&ret_y,0,0);
|
|
|
|
if(face)
|
|
return(1);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
SLONG foot_hold_available_obj(Thing *p_person,SLONG dx,SLONG dy,SLONG dz,SLONG obj)
|
|
{
|
|
SLONG rdx,rdz;
|
|
SLONG angle;
|
|
SLONG wx,wy,wz;
|
|
SLONG px,py,pz,ret_y,face;
|
|
|
|
angle=p_person->Draw.Tweened->Angle;
|
|
|
|
rdx=(dx*COS(angle)-dz*SIN(angle))>>16;
|
|
rdz=(dx*SIN(angle)+dz*COS(angle))>>16;
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,obj,&wx,&wy,&wz);
|
|
|
|
px=(p_person->WorldPos.X>>8)+rdx+wx;
|
|
py=(p_person->WorldPos.Y>>8)+wy;
|
|
pz=(p_person->WorldPos.Z>>8)+rdz+wz;
|
|
|
|
face=find_face_for_this_pos(px,py,pz,&ret_y,0,0);
|
|
|
|
if(face)
|
|
return(1);
|
|
else
|
|
return(0);
|
|
}
|
|
#endif
|
|
void set_person_flip(Thing *p_person,SLONG dir)
|
|
{
|
|
MSG_add(" start flipping");
|
|
switch(dir)
|
|
{
|
|
case 0:
|
|
// if(!foot_hold_available(p_person,100,0,0))
|
|
// return;
|
|
|
|
set_anim(p_person,ANIM_FLIP_LEFT);
|
|
p_person->Genus.Person->Action = ACTION_FLIP_LEFT;
|
|
break;
|
|
|
|
case 1:
|
|
// if(!foot_hold_available(p_person,-100,0,0))
|
|
// return;
|
|
|
|
set_anim(p_person,ANIM_FLIP_RIGHT);
|
|
p_person->Genus.Person->Action = ACTION_FLIP_RIGHT;
|
|
break;
|
|
|
|
}
|
|
// set_thing_velocity(p_person,40);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_FLIPING;
|
|
p_person->Genus.Person->Flags|=(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
}
|
|
|
|
void set_person_running(Thing *p_person)
|
|
{
|
|
|
|
p_person->Draw.Tweened->Locked = 0;
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
camera_normal();
|
|
}
|
|
|
|
if(p_person->Genus.Person->Flags2 & FLAG2_PERSON_CARRYING)
|
|
{
|
|
Thing *p_target;
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
set_anim(p_person,ANIM_START_WALK_CARRY);
|
|
set_anim(p_target,ANIM_START_WALK_CARRY_V);
|
|
p_target->SubState=SUB_STATE_CARRY_MOVE_V;
|
|
|
|
goto run;
|
|
|
|
}
|
|
|
|
|
|
switch(p_person->Genus.Person->Mode)
|
|
{
|
|
case PERSON_MODE_WALK:
|
|
set_person_walking(p_person);
|
|
break;
|
|
case PERSON_MODE_SPRINT:
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
goto yomp;
|
|
|
|
set_anim_running(p_person);
|
|
goto run;
|
|
case PERSON_MODE_RUN:
|
|
case PERSON_MODE_FIGHT:
|
|
// if(p_person->Genus.Person->AnimType!=ANIM_TYPE_ROPER) //I don't like yomp_start
|
|
yomp:;
|
|
// if(person_holding_2handed(p_person))
|
|
|
|
if(person_holding_bat(p_person))
|
|
{
|
|
set_anim(p_person,ANIM_YOMP_START_BAT);
|
|
|
|
}
|
|
else
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
set_anim(p_person,ANIM_YOMP_START_AK);
|
|
|
|
//
|
|
// de-target
|
|
//
|
|
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
set_anim(p_person,ANIM_YOMP_START_PISTOL);
|
|
|
|
}
|
|
else
|
|
set_anim(p_person,ANIM_YOMP_START);
|
|
}
|
|
if (p_person->Genus.Person->PlayerID)
|
|
p_person->Genus.Person->Target=0;
|
|
// else
|
|
// set_anim(p_person,ANIM_YOMP);
|
|
run:;
|
|
// set_thing_velocity(p_person,15);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_RUNNING;
|
|
if(p_person->Genus.Person->Flags2 & FLAG2_PERSON_CARRYING)
|
|
p_person->Genus.Person->Action = ACTION_NONE;
|
|
else
|
|
p_person->Genus.Person->Action = ACTION_RUN;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
break;
|
|
case PERSON_MODE_SNEAK:
|
|
set_person_sneaking(p_person);
|
|
break;
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
|
|
void set_person_running_frame(Thing *p_person,SLONG frame)
|
|
{
|
|
switch(p_person->Genus.Person->Mode)
|
|
{
|
|
case 0:
|
|
MSG_add(" start running");
|
|
queue_anim(p_person,ANIM_RUN);
|
|
|
|
// set_thing_velocity(p_person,15);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_RUNNING;
|
|
p_person->Genus.Person->Action = ACTION_RUN;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
while(frame)
|
|
{
|
|
p_person->Draw.Tweened->QueuedFrame=p_person->Draw.Tweened->QueuedFrame->NextFrame;
|
|
frame--;
|
|
}
|
|
break;
|
|
case 1:
|
|
set_person_walking(p_person);
|
|
break;
|
|
case 2:
|
|
set_person_sneaking(p_person);
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void set_person_draw_special(Thing *p_person)
|
|
{
|
|
Thing *p_special = NULL;
|
|
/*
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
//
|
|
// Put away your gun.
|
|
//
|
|
|
|
set_person_gun_away(p_person);
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
//
|
|
// Make p_person use an item.
|
|
//
|
|
|
|
if (p_person->Genus.Person->SpecialUse == NULL)
|
|
{
|
|
//
|
|
// Use her first item.
|
|
//
|
|
|
|
if (p_person->Genus.Person->SpecialList)
|
|
{
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialList);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
if (p_special->Genus.Special->NextSpecial)
|
|
{
|
|
p_special = TO_THING(p_special->Genus.Special->NextSpecial);
|
|
}
|
|
else
|
|
{
|
|
p_special = NULL;
|
|
}
|
|
}
|
|
|
|
if (p_special)
|
|
{
|
|
set_person_draw_item(p_person, p_special->Genus.Special->SpecialType);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
p_person->Genus.Person->SpecialUse = NULL;
|
|
p_person->Draw.Tweened->PersonID = 0;
|
|
|
|
//
|
|
// If p_person has a gun then get it out.
|
|
//
|
|
|
|
set_person_draw_gun(p_person);
|
|
*/
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make people notice.
|
|
//
|
|
|
|
PCOM_oscillate_tympanum(
|
|
PCOM_SOUND_DRAW_GUN,
|
|
p_person,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
}
|
|
|
|
void set_person_draw_gun(Thing *p_person)
|
|
{
|
|
if(p_person->Genus.Person->Flags2 & FLAG2_PERSON_CARRYING)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!(p_person->Flags & FLAGS_HAS_GUN))
|
|
{
|
|
return;
|
|
}
|
|
|
|
MSG_add(" start draw gun");
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
set_anim(p_person,ANIM_PISTOL_DRAW);
|
|
set_thing_velocity(p_person,0);
|
|
set_generic_person_state_function(p_person,STATE_GUN);
|
|
|
|
p_person->SubState = SUB_STATE_DRAW_GUN;
|
|
p_person->Genus.Person->Action = ACTION_DRAW_SPECIAL;
|
|
p_person->Genus.Person->SpecialDraw = NULL;
|
|
p_person->Genus.Person->SpecialUse = NULL;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NON_INT_C | FLAG_PERSON_NON_INT_M;
|
|
p_person->Genus.Person->Target = NULL;
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
camera_shoot();
|
|
}
|
|
|
|
//
|
|
// You can't be in fight mode with a gun out!
|
|
//
|
|
|
|
if (p_person->Genus.Person->Mode == PERSON_MODE_FIGHT)
|
|
{
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
}
|
|
|
|
//
|
|
// Make people notice.
|
|
//
|
|
|
|
PCOM_oscillate_tympanum(
|
|
PCOM_SOUND_DRAW_GUN,
|
|
p_person,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
}
|
|
|
|
void set_person_gun_away(Thing *p_person)
|
|
{
|
|
/*
|
|
if (!(p_person->Flags & FLAGS_HAS_GUN))
|
|
{
|
|
return;
|
|
}
|
|
*/
|
|
|
|
p_person->Genus.Person->SpecialUse = NULL;
|
|
p_person->Draw.Tweened->PersonID&= ~0xe0;
|
|
// p_person->Draw.Tweened->PersonID=0;
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_GUN_OUT;
|
|
set_person_idle(p_person);
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
camera_normal();
|
|
}
|
|
}
|
|
|
|
|
|
void set_person_step_left(Thing *p_person)
|
|
{
|
|
MSG_add(" start step_left");
|
|
if(p_person->SubState == SUB_STATE_STEP_LEFT)
|
|
return;
|
|
set_anim(p_person,ANIM_STEP_LEFT);
|
|
set_thing_velocity(p_person,0);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
// p_person->State=STATE_MOVEING;
|
|
p_person->SubState = SUB_STATE_STEP_LEFT;
|
|
p_person->Genus.Person->Action = ACTION_SIDE_STEP;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
// p_person->Genus.Person->Flags|=FLAG_PERSON_LOCK_ANIM_CHANGE;
|
|
}
|
|
|
|
void set_person_step_right(Thing *p_person)
|
|
{
|
|
MSG_add(" start step_left");
|
|
if(p_person->SubState == SUB_STATE_STEP_RIGHT)
|
|
return;
|
|
set_anim(p_person,ANIM_STEP_RIGHT);
|
|
set_thing_velocity(p_person,0);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
// p_person->State=STATE_MOVEING;
|
|
p_person->SubState = SUB_STATE_STEP_RIGHT;
|
|
p_person->Genus.Person->Action = ACTION_SIDE_STEP;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
// p_person->Genus.Person->Flags|=FLAG_PERSON_LOCK_ANIM_CHANGE;
|
|
}
|
|
|
|
void set_vehicle_anim(Thing *p_vehicle,SLONG anim)
|
|
{
|
|
// 1 is still
|
|
// 2 is open/close
|
|
ASSERT(0);
|
|
return;
|
|
p_vehicle->Genus.Vehicle->Draw.CurrentFrame=game_chunk[5].AnimList[anim];
|
|
p_vehicle->Genus.Vehicle->Draw.AnimTween=0;
|
|
|
|
if(anim==2)
|
|
{
|
|
p_vehicle->Genus.Vehicle->Draw.NextFrame=p_vehicle->Genus.Vehicle->Draw.CurrentFrame->NextFrame;
|
|
}
|
|
else
|
|
{
|
|
p_vehicle->Genus.Vehicle->Draw.NextFrame=p_vehicle->Genus.Vehicle->Draw.CurrentFrame;
|
|
}
|
|
}
|
|
|
|
void get_car_enter_xz(Thing *p_vehicle,SLONG door,SLONG *cx,SLONG *cz);
|
|
|
|
void position_person_for_vehicle(Thing *p_person,Thing *p_vehicle,SLONG door)
|
|
{
|
|
SLONG ix,iz;
|
|
GameCoord new_position;
|
|
|
|
ASSERT(door == 0 || door == 1);
|
|
|
|
get_car_enter_xz(p_vehicle,door,&ix,&iz);
|
|
|
|
new_position.X=ix<<8;
|
|
new_position.Z=iz<<8;
|
|
|
|
new_position.Y=p_person->WorldPos.Y;//PAP_calc_map_height_at(ix,iz)<<8;
|
|
move_thing_on_map(p_person,&new_position);
|
|
|
|
p_person->Draw.Tweened->Angle = p_vehicle->Genus.Vehicle->Angle;
|
|
|
|
if (door)
|
|
{
|
|
p_person->Draw.Tweened->Angle += 512;
|
|
}
|
|
else
|
|
{
|
|
p_person->Draw.Tweened->Angle -= 512;
|
|
}
|
|
|
|
p_person->Draw.Tweened->Angle &= 2047;
|
|
|
|
}
|
|
|
|
void set_person_enter_vehicle(Thing *p_person,Thing *p_vehicle, SLONG door)
|
|
{
|
|
ASSERT(door == 0 || door == 1);
|
|
|
|
if (p_vehicle->Genus.Vehicle->Driver)
|
|
{
|
|
//
|
|
// This vehicle is already occupied.
|
|
//
|
|
|
|
p_person->Genus.Person->InCar = 0;
|
|
return;
|
|
}
|
|
|
|
if (p_vehicle->State == STATE_DEAD)
|
|
{
|
|
//
|
|
// Broken car!
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
if (p_vehicle->Genus.Vehicle->key != SPECIAL_NONE)
|
|
{
|
|
//
|
|
// We can only get into this car if we have the right key.
|
|
//
|
|
|
|
if (!person_has_special(p_person, p_vehicle->Genus.Vehicle->key))
|
|
{
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
//CONSOLE_text("The car is locked");
|
|
/*
|
|
extern void add_damage_text(SWORD x,SWORD y,SWORD z,CBYTE *text);
|
|
|
|
add_damage_text(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y + 0x6000 >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
XLAT_str(X_CAR_LOCKED));
|
|
*/
|
|
PANEL_new_info_message(XLAT_str(X_CAR_LOCKED));
|
|
}
|
|
|
|
p_person->Genus.Person->InCar = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
set_thing_velocity(p_person,0);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_ENTERING_VEHICLE;
|
|
p_person->Genus.Person->Action = ACTION_ENTER_VEHICLE;
|
|
p_person->Genus.Person->Flags|=(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
{
|
|
// NASTY HACK! This extern changes the behaviour of get_car_door_offsets()
|
|
// in vehicle.cpp!
|
|
|
|
extern UBYTE sneaky_do_it_for_positioning_a_person_to_do_the_enter_anim;
|
|
|
|
sneaky_do_it_for_positioning_a_person_to_do_the_enter_anim = TRUE;
|
|
|
|
position_person_for_vehicle(p_person,p_vehicle,door);
|
|
|
|
sneaky_do_it_for_positioning_a_person_to_do_the_enter_anim = FALSE;
|
|
}
|
|
|
|
// set_locked_anim(p_person,ANIM_DANCE_BOOGIE,SUB_OBJECT_LEFT_FOOT);
|
|
set_locked_anim(p_person,(door) ? ANIM_ENTER_TAXI : ANIM_ENTER_CAR,SUB_OBJECT_LEFT_FOOT);
|
|
p_person->Genus.Person->InCar = THING_NUMBER(p_vehicle);
|
|
// set_vehicle_anim(p_vehicle,2);
|
|
p_vehicle->Genus.Vehicle->Flags|=FLAG_VEH_ANIMATING;
|
|
|
|
|
|
MFX_play_thing(THING_NUMBER(p_vehicle),S_CAR_DOOR,0,p_vehicle);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Adds a person to the linked list of people who are passengers in
|
|
// the given vehicle.
|
|
//
|
|
|
|
void add_person_to_passenger_list(Thing *p_person, Thing *p_vehicle)
|
|
{
|
|
ASSERT(p_person->Class == CLASS_PERSON);
|
|
ASSERT(p_vehicle->Class == CLASS_VEHICLE);
|
|
|
|
p_person ->Genus.Person ->Passenger = p_vehicle->Genus.Vehicle->Passenger;
|
|
p_vehicle->Genus.Vehicle->Passenger = THING_NUMBER(p_person);
|
|
}
|
|
|
|
//
|
|
// Removes a person from the passenger list of the given vehicle.
|
|
//
|
|
|
|
void remove_person_from_passenger_list(Thing *p_person, Thing *p_vehicle)
|
|
{
|
|
Thing *p_passenger;
|
|
|
|
ASSERT(p_person->Class == CLASS_PERSON);
|
|
ASSERT(p_vehicle->Class == CLASS_VEHICLE);
|
|
|
|
ASSERT(p_person->Genus.Person->Flags & FLAG_PERSON_PASSENGER);
|
|
|
|
UWORD next;
|
|
UWORD *prev;
|
|
|
|
prev = &p_vehicle->Genus.Vehicle->Passenger;
|
|
next = p_vehicle->Genus.Vehicle->Passenger;
|
|
|
|
while(1)
|
|
{
|
|
if (next == NULL)
|
|
{
|
|
ASSERT(0);
|
|
|
|
//
|
|
// The person wasn't a passenger in this vehicle!
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
p_passenger = TO_THING(next);
|
|
|
|
ASSERT(p_passenger->Class == CLASS_PERSON);
|
|
|
|
if (p_passenger == p_person)
|
|
{
|
|
//
|
|
// We have found who to delete.
|
|
//
|
|
|
|
*prev = p_person->Genus.Person->Passenger;
|
|
|
|
return;
|
|
}
|
|
|
|
prev = &p_passenger->Genus.Person->Passenger;
|
|
next = p_passenger->Genus.Person->Passenger;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void set_person_passenger_in_vehicle(Thing *p_person, Thing *p_vehicle, SLONG door)
|
|
{
|
|
//
|
|
// No animation. Just pop in!
|
|
//
|
|
|
|
set_thing_velocity(p_person,0);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
remove_thing_from_map(p_person);
|
|
add_person_to_passenger_list(p_person, p_vehicle);
|
|
|
|
p_person->SubState = SUB_STATE_INSIDE_VEHICLE;
|
|
p_person->Genus.Person->Action = ACTION_INSIDE_VEHICLE;
|
|
p_person->Genus.Person->Flags |= (FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C|FLAG_PERSON_PASSENGER);
|
|
p_person->Genus.Person->InCar = THING_NUMBER(p_vehicle);
|
|
}
|
|
|
|
|
|
void set_person_exit_vehicle(Thing *p_person)
|
|
{
|
|
Thing *p_vehicle;
|
|
|
|
p_vehicle = TO_THING(p_person->Genus.Person->InCar);
|
|
|
|
//
|
|
// Where do we want this person to appear?
|
|
//
|
|
|
|
SLONG door_x;
|
|
SLONG door_y;
|
|
SLONG door_z;
|
|
SLONG side;
|
|
SLONG otherside = FALSE;
|
|
SLONG dx,dz;
|
|
|
|
GameCoord newpos;
|
|
|
|
side = (p_person->Genus.Person->Flags & FLAG_PERSON_PASSENGER);
|
|
|
|
try_again:;
|
|
|
|
|
|
VEH_find_door(
|
|
p_vehicle,
|
|
side,
|
|
&door_x,
|
|
&door_z);
|
|
|
|
//
|
|
// Is there a fence or a wall in the way?
|
|
//
|
|
|
|
dx = 0;//(door_x - (p_vehicle->WorldPos.X >> 8)) >> 2;
|
|
dz = 0;//(door_z - (p_vehicle->WorldPos.Z >> 8)) >> 2;
|
|
|
|
SLONG mx = door_x + dx >> 8;
|
|
SLONG mz = door_z + dz >> 8;
|
|
|
|
door_y = PAP_calc_map_height_at(door_x + dx,door_z + dz);
|
|
|
|
#ifndef TARGET_DC
|
|
#ifndef NDEBUG
|
|
|
|
AENG_world_line(
|
|
p_vehicle->WorldPos.X >> 8,
|
|
p_vehicle->WorldPos.Y >> 8,
|
|
p_vehicle->WorldPos.Z >> 8,
|
|
32,
|
|
0xffffff,
|
|
door_x+dx,
|
|
door_y,
|
|
door_z+dz,
|
|
0,
|
|
0x03f008,
|
|
TRUE);
|
|
|
|
#endif
|
|
#endif
|
|
|
|
if (abs(door_y-(p_person->WorldPos.Y>>8))>150 || (PAP_2HI(mx,mz).Flags & PAP_FLAG_NOGO) || !there_is_a_los(
|
|
p_vehicle->WorldPos.X >> 8,
|
|
p_vehicle->WorldPos.Y + 0x6000 >> 8,
|
|
p_vehicle->WorldPos.Z >> 8,
|
|
door_x + dx,
|
|
door_y + 0x60,
|
|
door_z + dz,
|
|
LOS_FLAG_IGNORE_SEETHROUGH_FENCE_FLAG |
|
|
LOS_FLAG_IGNORE_PRIMS |
|
|
LOS_FLAG_IGNORE_UNDERGROUND_CHECK))
|
|
{
|
|
//
|
|
// There is something in the way- bin this message because sometimes
|
|
// you simply can't move the car.
|
|
//
|
|
|
|
/*
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// Tell the player that he can't get out of the car there.
|
|
//
|
|
|
|
PANEL_new_help_message("You can't open the door to get out of the vehicle!");
|
|
|
|
return;
|
|
}
|
|
|
|
*/
|
|
|
|
if (!otherside)
|
|
{
|
|
//
|
|
// Try getting out the passenger side.
|
|
//
|
|
|
|
side = !side;
|
|
otherside = TRUE;
|
|
|
|
goto try_again;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This is unfortunate! There is a person who wants to get out of the vehicle
|
|
// but he can't open any of the doors... Just make him exit _inside_ the
|
|
// vehicle!
|
|
//
|
|
|
|
door_x = p_vehicle->WorldPos.X >> 8;
|
|
door_z = p_vehicle->WorldPos.Z >> 8;
|
|
}
|
|
}
|
|
|
|
|
|
newpos.X = door_x << 8;
|
|
newpos.Y = PAP_calc_map_height_at(door_x,door_z);
|
|
newpos.Z = door_z << 8;
|
|
|
|
move_thing_on_map(p_person, &newpos);
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_PASSENGER)
|
|
{
|
|
//
|
|
// Get out of the car.
|
|
//
|
|
|
|
remove_person_from_passenger_list(p_person, p_vehicle);
|
|
|
|
p_person->Genus.Person->Flags &= ~(FLAG_PERSON_PASSENGER|FLAG_PERSON_DRIVING);
|
|
p_person->Genus.Person->InCar = NULL;
|
|
p_person->Genus.Person->Passenger = NULL;
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Flags &= ~(FLAG_PERSON_PASSENGER|FLAG_PERSON_DRIVING);
|
|
p_person->Genus.Person->InCar = NULL;
|
|
p_vehicle->Genus.Vehicle->Flags &= ~FLAG_FURN_DRIVING;
|
|
p_vehicle->Genus.Vehicle->Driver = NULL;
|
|
|
|
#ifndef PSX
|
|
MFX_stop(THING_NUMBER(p_vehicle),S_CARX_START);
|
|
MFX_stop(THING_NUMBER(p_vehicle),S_CARX_CRUISE);
|
|
MFX_stop(THING_NUMBER(p_vehicle),S_CARX_IDLE);
|
|
#endif
|
|
if (p_vehicle->Genus.Vehicle->Flags&FLAG_VEH_FX_STATE) {
|
|
// MFX_play_thing(THING_NUMBER(p_vehicle),S_CARX_DECEL,MFX_MOVING|MFX_EARLY_OUT,p_vehicle);
|
|
p_vehicle->Genus.Vehicle->Flags&=~FLAG_VEH_FX_STATE;
|
|
}
|
|
MFX_stop(THING_NUMBER(p_vehicle),MFX_WAVE_ALL);
|
|
#ifndef PSX
|
|
MFX_play_thing(THING_NUMBER(p_vehicle),S_CARX_END,0,p_vehicle);
|
|
#endif
|
|
}
|
|
|
|
add_thing_to_map(p_person);
|
|
set_person_idle(p_person);
|
|
plant_feet(p_person);
|
|
}
|
|
|
|
#ifdef BIKE
|
|
void position_person_for_mounting_bike(Thing *p_person, Thing *p_bike)
|
|
{
|
|
GameCoord newpos;
|
|
SLONG vector[3];
|
|
|
|
FMATRIX_vector(
|
|
vector,
|
|
(p_bike->Draw.Tweened->Angle + 1024) & 2047,
|
|
0);
|
|
|
|
newpos = p_bike->WorldPos;
|
|
|
|
switch(p_person->Genus.Person->AnimType) {
|
|
/*
|
|
case ANIM_TYPE_ROPER:
|
|
newpos.X += vector[2] * 30 >> 8;
|
|
newpos.Y -= 0x1800;
|
|
newpos.Z -= vector[0] * 30 >> 8;
|
|
|
|
newpos.X += vector[0] * 50 >> 8;
|
|
newpos.Z += vector[2] * 50 >> 8;
|
|
|
|
break;
|
|
*/
|
|
default:
|
|
|
|
newpos.X += vector[2] * 60 >> 8;
|
|
newpos.Y -= 0x2800;
|
|
newpos.Z -= vector[0] * 60 >> 8;
|
|
|
|
newpos.X += vector[0] * 30 >> 8;
|
|
newpos.Z += vector[2] * 30 >> 8;
|
|
|
|
break;
|
|
}
|
|
|
|
move_thing_on_map(p_person, &newpos);
|
|
|
|
p_person->Draw.Tweened->Angle = (p_bike->Draw.Tweened->Angle - 512) & 2047;
|
|
}
|
|
|
|
|
|
void set_person_mount_bike(Thing *p_person, Thing *p_bike)
|
|
{
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
|
|
set_anim(p_person, ANIM_BIKE_MOUNT);
|
|
|
|
//
|
|
// Position the person for getting on the bike.
|
|
//
|
|
|
|
position_person_for_mounting_bike(p_person, p_bike);
|
|
|
|
p_person->SubState = SUB_STATE_MOUNTING_BIKE;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_BIKING | FLAG_PERSON_NON_INT_M | FLAG_PERSON_NON_INT_C;
|
|
p_person->Genus.Person->InCar = THING_NUMBER(p_bike);
|
|
p_person->Genus.Person->Action = ACTION_ENTER_VEHICLE;
|
|
|
|
//
|
|
// Tell the bike that somebody is getting on it.
|
|
//
|
|
|
|
BIKE_set_mounting(p_bike, p_person);
|
|
}
|
|
|
|
void set_person_dismount_bike(Thing *p_person)
|
|
{
|
|
//
|
|
// Tell the bike to play its dismount anim.
|
|
//
|
|
|
|
void BIKE_set_dismounting(Thing *p_bike);
|
|
|
|
Thing *p_bike = TO_THING(p_person->Genus.Person->InCar);
|
|
|
|
BIKE_set_dismounting(p_bike);
|
|
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
|
|
set_anim(p_person, ANIM_BIKE_DISMOUNT);
|
|
|
|
// position_person_for_mounting_bike(p_person, p_bike);
|
|
|
|
p_person->SubState = SUB_STATE_DISMOUNTING_BIKE;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_BIKING | FLAG_PERSON_NON_INT_M | FLAG_PERSON_NON_INT_C;
|
|
p_person->Genus.Person->Action = ACTION_ENTER_VEHICLE; // Enter.. exit.. whats the difference!
|
|
|
|
/*
|
|
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_BIKING;
|
|
p_person->Genus.Person->InCar = 0;
|
|
|
|
p_person->Draw.Tweened->Tilt=0;
|
|
set_person_idle(p_person);
|
|
|
|
*/
|
|
|
|
//
|
|
// Position the person for getting on the bike.
|
|
//
|
|
|
|
position_person_for_mounting_bike(p_person, p_bike);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
void set_anim_walking(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
if(p_person->Genus.Person->PersonType!=PERSON_DARCI && p_person->Genus.Person->PersonType!=PERSON_ROPER)
|
|
{
|
|
set_anim(p_person,ANIM_THUG_WALK_SHOTGUN);
|
|
return;
|
|
}
|
|
|
|
}
|
|
if(p_person->Genus.Person->PersonType == PERSON_THUG_RASTA ||
|
|
p_person->Genus.Person->PersonType == PERSON_THUG_RED ||
|
|
p_person->Genus.Person->PersonType == PERSON_THUG_GREY)
|
|
{
|
|
set_anim(p_person,ANIM_THUG_WALK);
|
|
}
|
|
else
|
|
|
|
if(p_person->Genus.Person->PersonType==PERSON_COP)
|
|
{
|
|
SLONG old;
|
|
old=p_person->Genus.Person->AnimType;
|
|
set_anim_of_type(p_person,COP_ROPER_ANIM_WALK,ANIM_TYPE_ROPER);
|
|
p_person->Genus.Person->AnimType=old;
|
|
}
|
|
else
|
|
if(p_person->Genus.Person->PersonType==PERSON_CIV)
|
|
{
|
|
switch(p_person->Draw.Tweened->MeshID)
|
|
{
|
|
case 7:
|
|
case 8:
|
|
set_anim_of_type(p_person,CIV_M_ANIM_WALK,ANIM_TYPE_CIV);
|
|
break;
|
|
case 9:
|
|
set_anim_of_type(p_person,CIV_F_ANIM_WALK,ANIM_TYPE_CIV);
|
|
break;
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
set_anim(p_person,ANIM_WALK);
|
|
}
|
|
|
|
}
|
|
|
|
void set_anim_running(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
{
|
|
set_anim(p_person,ANIM_YOMP); //roper dont have a sprint
|
|
}
|
|
else
|
|
if(p_person->Genus.Person->PersonType==PERSON_COP)
|
|
{
|
|
SLONG old;
|
|
old=p_person->Genus.Person->AnimType;
|
|
set_anim_of_type(p_person,COP_ROPER_ANIM_RUN,ANIM_TYPE_ROPER);
|
|
p_person->Genus.Person->AnimType=old;
|
|
}
|
|
else
|
|
if(p_person->Genus.Person->PersonType==PERSON_CIV)
|
|
{
|
|
SLONG old;
|
|
switch(p_person->Draw.Tweened->MeshID)
|
|
{
|
|
case 7:
|
|
case 8:
|
|
set_anim_of_type(p_person,CIV_M_ANIM_RUN,ANIM_TYPE_CIV);
|
|
break;
|
|
case 9:
|
|
set_anim_of_type(p_person,CIV_F_ANIM_RUN,ANIM_TYPE_CIV);
|
|
break;
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if (person_has_gun_out(p_person))
|
|
{
|
|
set_anim(p_person, ANIM_AK_JOG);
|
|
}
|
|
else
|
|
{
|
|
set_anim(p_person,ANIM_RUN);
|
|
}
|
|
}
|
|
|
|
}
|
|
void set_anim_idle(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
|
|
if (p_person->Genus.Person->Mode == PERSON_MODE_FIGHT)
|
|
{
|
|
anim=find_idle_fight_stance(p_person);
|
|
|
|
}
|
|
else
|
|
{
|
|
if(person_holding_2handed(p_person) && p_person->Genus.Person->PersonType!=PERSON_ROPER)
|
|
{
|
|
anim=ANIM_SHOTGUN_IDLE;
|
|
set_anim(p_person,anim);
|
|
}
|
|
else
|
|
{
|
|
|
|
switch(p_person->Genus.Person->PersonType)
|
|
{
|
|
case PERSON_SLAG_TART:
|
|
case PERSON_SLAG_FATUGLY:
|
|
set_anim(p_person,ANIM_STAND_HIP);
|
|
break;
|
|
case PERSON_CIV:
|
|
switch(p_person->Draw.Tweened->MeshID)
|
|
{
|
|
case 7:
|
|
case 8:
|
|
set_anim_of_type(p_person,CIV_M_ANIM_STAND,ANIM_TYPE_CIV);
|
|
break;
|
|
case 9:
|
|
set_anim(p_person,ANIM_STAND_HIP);
|
|
|
|
break;
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
|
|
}
|
|
break;
|
|
case PERSON_COP:
|
|
set_anim_of_type(p_person,COP_ROPER_ANIM_READY,ANIM_TYPE_ROPER);
|
|
break;
|
|
default:
|
|
anim = ANIM_STAND_READY;
|
|
set_anim(p_person,anim);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void set_person_walking(Thing *p_person)
|
|
{
|
|
set_anim_walking(p_person);
|
|
|
|
set_thing_velocity(p_person,5);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_WALKING;
|
|
p_person->Genus.Person->Action = ACTION_WALK;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
}
|
|
void set_person_walk_backwards(Thing *p_person)
|
|
{
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
set_anim(p_person,ANIM_BACK_WALK_AK);
|
|
}
|
|
else
|
|
{
|
|
set_anim(p_person,ANIM_BACK_WALK);
|
|
}
|
|
|
|
|
|
set_thing_velocity(p_person,-5);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_WALKING_BACKWARDS;
|
|
p_person->Genus.Person->Action = ACTION_WALK;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
}
|
|
|
|
void set_person_sneaking(Thing *p_person)
|
|
{
|
|
set_anim(p_person,ANIM_SNEAK);
|
|
|
|
set_thing_velocity(p_person,5);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_WALKING;
|
|
p_person->Genus.Person->Action = ACTION_WALK;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
}
|
|
|
|
void set_person_hop_back(Thing *p_person)
|
|
{
|
|
// p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_WALK];
|
|
// p_person->Draw.Tweened->CurrentAnim = ANIM_WALK;
|
|
set_thing_velocity(p_person,0);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_HOP_BACK;
|
|
p_person->Genus.Person->Action = ACTION_HOP_BACK;
|
|
p_person->Genus.Person->Timer1=3;
|
|
p_person->Genus.Person->Flags|=(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
// queue_anim(p_person,ANIM_BSTEP);
|
|
// set_locked_anim(p_person,ANIM_WALK,0);
|
|
set_anim(p_person,ANIM_BACK_HOP);
|
|
}
|
|
|
|
SLONG find_idle_fight_stance(Thing *p_person)
|
|
{
|
|
SLONG anim=ANIM_FIGHT;
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special;
|
|
|
|
//
|
|
// This person is using an item.
|
|
//
|
|
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
switch(p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_KNIFE:
|
|
anim=ANIM_KNIFE_FIGHT_READY;
|
|
break;
|
|
|
|
case SPECIAL_BASEBALLBAT:
|
|
anim=ANIM_BAT_IDLE;
|
|
|
|
break;
|
|
case SPECIAL_SHOTGUN:
|
|
case SPECIAL_AK47:
|
|
break;
|
|
}
|
|
}
|
|
return(anim);
|
|
}
|
|
|
|
void set_person_fight_idle(Thing *p_person)
|
|
{
|
|
SLONG anim; //=ANIM_FIGHT;
|
|
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_KO; //bodge
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
Thing *p_attacker = is_person_under_attack_low_level(p_person, FALSE, 0x200);
|
|
|
|
if (p_attacker == NULL)
|
|
{
|
|
//
|
|
// nobody to fight, then exit fight mode
|
|
//
|
|
p_person->Genus.Person->Agression=0;
|
|
p_person->Genus.Person->Mode=PERSON_MODE_RUN;
|
|
p_person->Genus.Person->Target=0;
|
|
set_person_idle(p_person);
|
|
if(p_person->State==STATE_IDLE)
|
|
set_anim(p_person,ANIM_UNFIGHT);
|
|
GAME_FLAGS&=~GF_SIDE_ON_COMBAT;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
person_enter_fight_mode(p_person); //for fuck's sake get in fight mode
|
|
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
|
|
anim=find_idle_fight_stance(p_person);
|
|
if(person_on_floor(p_person))
|
|
{
|
|
set_anim(p_person,anim);
|
|
}
|
|
else
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_RIGHT_FOOT,anim); //LEFT or right?
|
|
}
|
|
|
|
p_person->Draw.Tweened->AnimTween=0;
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_IDLE;//fight_idle
|
|
p_person->SubState=0;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
plant_feet(p_person);
|
|
|
|
//set_person_sidle(p_person);
|
|
}
|
|
|
|
void set_person_fight_step(Thing *p_person,SLONG dir)
|
|
{
|
|
SLONG anim;
|
|
p_person->Genus.Person->Timer1=0;
|
|
if(person_holding_bat(p_person))
|
|
{
|
|
switch(dir)
|
|
{
|
|
case 0:
|
|
anim=ANIM_FIGHT_STEP_N_BAT;
|
|
break;
|
|
case 1:
|
|
anim=ANIM_FIGHT_STEP_E_BAT;
|
|
break;
|
|
case 2:
|
|
anim=ANIM_FIGHT_STEP_S_BAT;
|
|
break;
|
|
case 3:
|
|
anim=ANIM_FIGHT_STEP_W_BAT;
|
|
break;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch(dir)
|
|
{
|
|
case 0:
|
|
anim=ANIM_FIGHT_STEP_N;
|
|
break;
|
|
case 1:
|
|
anim=ANIM_FIGHT_STEP_E;
|
|
break;
|
|
case 2:
|
|
anim=ANIM_FIGHT_STEP_S;
|
|
break;
|
|
case 3:
|
|
anim=ANIM_FIGHT_STEP_W;
|
|
break;
|
|
|
|
}
|
|
}
|
|
if(anim==p_person->Draw.Tweened->CurrentAnim)
|
|
return;
|
|
set_locked_anim(p_person, anim,SUB_OBJECT_LEFT_FOOT);
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
p_person->SubState=SUB_STATE_STEP_FORWARD;
|
|
p_person->Velocity=(p_person->Genus.Person->AnimType==ANIM_TYPE_ROPER) ? 10 : 20;
|
|
p_person->Genus.Person->Timer1=0;
|
|
|
|
}
|
|
|
|
void set_person_fight_step_forward(Thing *p_person)
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim !=ANIM_FIGHT_STEP_N)
|
|
{
|
|
set_anim(p_person,ANIM_FIGHT_STEP_N);
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
p_person->SubState=SUB_STATE_STEP_FORWARD;
|
|
p_person->Velocity=10;
|
|
}
|
|
}
|
|
|
|
void set_person_block(Thing *p_person)
|
|
{
|
|
SLONG anim = ANIM_BLOCK_HIGH;
|
|
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special;
|
|
|
|
//
|
|
// This person might be using a weapon with its own special block anim.
|
|
//
|
|
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
switch (p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_BASEBALLBAT: anim = ANIM_BAT_BLOCK; break;
|
|
case SPECIAL_SHOTGUN: anim = ANIM_SHOTGUN_BLOCK; break;
|
|
}
|
|
}
|
|
|
|
if (anim)
|
|
{
|
|
p_person->Draw.Tweened->Locked=0;
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim); //was pelvis, but pelvis is bobbing in fight idle
|
|
p_person->Genus.Person->CombatNode=0;
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_FIGHT_PUNCH;
|
|
p_person->SubState=SUB_STATE_BLOCK;
|
|
p_person->Draw.Tweened->Locked=0; //-SUB_OBJECT_LEFT_FOOT;
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
}
|
|
}
|
|
|
|
void set_person_idle_croutch(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
anim=ANIM_IDLE_CROUTCH;
|
|
|
|
if(anim)
|
|
{
|
|
p_person->Draw.Tweened->Locked=0;
|
|
set_anim(p_person,anim);
|
|
|
|
p_person->Genus.Person->CombatNode=0;
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_CROUTCH;
|
|
p_person->SubState=SUB_STATE_IDLE_CROUTCHING;
|
|
|
|
p_person->Draw.Tweened->Locked=0; //-SUB_OBJECT_LEFT_FOOT;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Drops the person you are carrying in an emergency. e.g. if you just
|
|
// been hit or shot.
|
|
//
|
|
|
|
void emergency_uncarry(Thing *p_person)
|
|
{
|
|
ASSERT(p_person->Genus.Person->Flags2 & FLAG2_PERSON_CARRYING);
|
|
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
//
|
|
// Make the target plunge down.
|
|
//
|
|
|
|
p_target->DY = -(4 << 8);
|
|
p_target->OnFace = 0;
|
|
p_target->SubState = SUB_STATE_DYING_PRONE;
|
|
|
|
set_generic_person_state_function(p_target, STATE_DYING);
|
|
|
|
locked_anim_change(p_target,0,ANIM_PLUNGE_FORWARD);
|
|
|
|
//
|
|
// Stop carrying.
|
|
//
|
|
|
|
p_person->Genus.Person->Flags2 &= ~FLAG2_PERSON_CARRYING;
|
|
}
|
|
|
|
|
|
void carry_running(Thing *p_person)
|
|
{
|
|
Thing *p_target;
|
|
|
|
SLONG dx;
|
|
SLONG dz;
|
|
GameCoord new_position = p_person->WorldPos;
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
|
|
dx = -(SIN(p_person->Draw.Tweened->Angle) * 90) >> 8;
|
|
dz = -(COS(p_person->Draw.Tweened->Angle) * 90) >> 8;
|
|
new_position.X+=dx;
|
|
new_position.Z+=dz;
|
|
|
|
move_thing_on_map(p_target, &new_position);
|
|
p_target->Draw.Tweened->Angle=p_person->Draw.Tweened->Angle+1024;
|
|
p_target->Draw.Tweened->Angle&=2047;
|
|
}
|
|
void set_person_carry(Thing *p_person,SLONG s_index)
|
|
{
|
|
Thing *p_target;
|
|
SLONG dx;
|
|
SLONG dz;
|
|
GameCoord new_position = p_person->WorldPos;
|
|
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
p_person->Genus.Person->Flags2 |= FLAG2_PERSON_CARRYING;
|
|
|
|
dx = -(SIN(p_person->Draw.Tweened->Angle) * 90) >> 8;
|
|
dz = -(COS(p_person->Draw.Tweened->Angle) * 90) >> 8;
|
|
new_position.X+=dx;
|
|
new_position.Z+=dz;
|
|
|
|
p_person->Genus.Person->Target=s_index;
|
|
p_target=TO_THING(s_index);
|
|
set_generic_person_state_function(p_person,STATE_CARRY);
|
|
set_anim(p_person,ANIM_PICKUP_CARRY);
|
|
p_person->SubState=SUB_STATE_PICKUP_CARRY;
|
|
|
|
// set_generic_person_state_function(p_target,STATE_CARRY);
|
|
set_anim(p_target,ANIM_PICKUP_CARRY_V);
|
|
p_target->SubState=SUB_STATE_PICKUP_CARRY_V;
|
|
|
|
move_thing_on_map(p_target, &new_position);
|
|
p_target->Draw.Tweened->Angle=p_person->Draw.Tweened->Angle+1024;
|
|
p_target->Draw.Tweened->Angle&=2047;
|
|
if(p_target->Genus.Person->Target)
|
|
{
|
|
remove_from_gang_attack(p_target,TO_THING(p_target->Genus.Person->Target));
|
|
}
|
|
}
|
|
|
|
void set_person_uncarry(Thing *p_person)
|
|
{
|
|
Thing *p_target;
|
|
GameCoord new_position = p_person->WorldPos;
|
|
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
set_generic_person_state_function(p_person,STATE_CARRY);
|
|
set_anim(p_person,ANIM_PUTDOWN_CARRY);
|
|
p_person->SubState=SUB_STATE_DROP_CARRY;
|
|
|
|
// set_generic_person_state_function(p_target,STATE_CARRY);
|
|
set_anim(p_target,ANIM_PUTDOWN_CARRY_V);
|
|
p_target->SubState=SUB_STATE_DROP_CARRY_V;
|
|
|
|
// move_thing_on_map(p_target, &new_position);
|
|
// p_target->Draw.Tweened->Angle=p_person->Draw.Tweened->Angle;
|
|
|
|
}
|
|
|
|
void set_person_stand_carry(Thing *p_person)
|
|
{
|
|
Thing *p_target;
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
set_generic_person_state_function(p_person,STATE_CARRY);
|
|
|
|
set_anim(p_person,ANIM_STAND_CARRY);
|
|
p_person->SubState=SUB_STATE_STAND_CARRY;
|
|
|
|
set_anim(p_target,ANIM_STAND_CARRY_V);
|
|
p_target->SubState=SUB_STATE_STAND_CARRY_V;
|
|
}
|
|
|
|
void fn_person_carry(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
Thing *p_target;
|
|
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_PICKUP_CARRY:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
set_person_stand_carry(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_DROP_CARRY:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
p_person->Genus.Person->Flags2&=~FLAG2_PERSON_CARRYING;
|
|
set_person_idle(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_STAND_CARRY:
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
GameCoord new_position = p_person->WorldPos;
|
|
|
|
|
|
dx = -(SIN(p_person->Draw.Tweened->Angle) * 90) >> 8;
|
|
dz = -(COS(p_person->Draw.Tweened->Angle) * 90) >> 8;
|
|
new_position.X+=dx;
|
|
new_position.Z+=dz;
|
|
move_thing_on_map(p_target, &new_position);
|
|
p_target->Draw.Tweened->Angle=(p_person->Draw.Tweened->Angle+1024)&2047;
|
|
p_target->Draw.Tweened->Roll =(2048-p_person->Draw.Tweened->Roll)&2047;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void set_person_arrest(Thing *p_person,SLONG s_index)
|
|
{
|
|
SLONG anim;
|
|
ASSERT(s_index);
|
|
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
anim=ANIM_ARREST_CROUTCH;//_DOWN;
|
|
|
|
p_person->Draw.Tweened->Locked=0;
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim);
|
|
|
|
p_person->Genus.Person->CombatNode=0;
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_CROUTCH;
|
|
p_person->SubState=SUB_STATE_IDLE_CROUTCH_ARREST;
|
|
|
|
p_person->Draw.Tweened->Locked=0; //-SUB_OBJECT_LEFT_FOOT;
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
p_person->Genus.Person->Target=s_index;
|
|
|
|
// p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
|
|
if(s_index)
|
|
{
|
|
SLONG ax,ay,az;
|
|
Thing *p_target;
|
|
SLONG dx,dz;
|
|
SLONG on_what_side;
|
|
GameCoord new_position;
|
|
|
|
p_target=TO_THING(s_index);
|
|
p_target->Genus.Person->Flags|=FLAG_PERSON_ARRESTED;
|
|
|
|
switch(p_target->Genus.Person->PersonType)
|
|
{
|
|
case PERSON_THUG_RASTA:
|
|
case PERSON_THUG_GREY:
|
|
case PERSON_THUG_RED:
|
|
case PERSON_MIB1:
|
|
case PERSON_MIB2:
|
|
case PERSON_MIB3:
|
|
stat_arrested_thug++;
|
|
break;
|
|
default:
|
|
stat_arrested_innocent++;
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
on_what_side=person_is_lying_on_what(p_target);
|
|
|
|
|
|
if(on_what_side==PERSON_ON_HIS_BACK)
|
|
{
|
|
set_locked_anim(p_target,ANIM_ARREST_ROLL,0);
|
|
p_target->SubState=SUB_STATE_DEAD_ARREST_TURN_OVER;
|
|
}
|
|
else
|
|
{
|
|
SLONG angle;
|
|
|
|
// angle=lie_down_angle(p_target->Draw.Tweened->CurrentAnim);
|
|
set_locked_anim(p_target,ANIM_ARREST_BE_CUFFED,0);
|
|
p_target->SubState=SUB_STATE_DEAD_CUFFED;
|
|
// p_target->Draw.Tweened->Angle+=1024;
|
|
p_target->Draw.Tweened->Angle&=2047;
|
|
|
|
}
|
|
|
|
calc_sub_objects_position(p_target,p_target->Draw.Tweened->AnimTween,SUB_OBJECT_PELVIS,&ax,&ay,&az);
|
|
|
|
ax+=p_target->WorldPos.X>>8;
|
|
ay+=p_target->WorldPos.Y>>8;
|
|
az+=p_target->WorldPos.Z>>8;
|
|
|
|
dx = (SIN(p_target->Draw.Tweened->Angle)*60)>>16;
|
|
dz = (COS(p_target->Draw.Tweened->Angle)*60)>>16;
|
|
|
|
ax-=dx;
|
|
az-=dz;
|
|
|
|
dx=((p_person->WorldPos.X>>8)-ax)<<8;
|
|
dz=((p_person->WorldPos.Z>>8)-az)<<8;
|
|
|
|
new_position.X = p_target->WorldPos.X+dx;
|
|
new_position.Y = p_target->WorldPos.Y;
|
|
new_position.Z = p_target->WorldPos.Z+dz;
|
|
|
|
move_thing_on_map(p_target, &new_position);
|
|
|
|
|
|
|
|
/*
|
|
new_position.X = ax<<8;
|
|
new_position.Y = p_person->WorldPos.Y;
|
|
new_position.Z = az<<8;
|
|
|
|
move_thing_on_map(p_person, &new_position);
|
|
*/
|
|
|
|
|
|
p_person->Draw.Tweened->Angle=(p_target->Draw.Tweened->Angle+1024)&2047;
|
|
|
|
|
|
|
|
if(!remove_from_gang_attack(p_target,p_person))
|
|
{
|
|
Thing *p_victim;
|
|
if(p_target->Genus.Person->Target)
|
|
{
|
|
|
|
p_victim=TO_THING(p_target->Genus.Person->Target);
|
|
if(p_victim->Class==CLASS_PERSON)
|
|
remove_from_gang_attack(p_target,p_victim);
|
|
}
|
|
}
|
|
|
|
//
|
|
// set them to dead so they can't get upto any funny business
|
|
//
|
|
set_generic_person_state_function(p_target,STATE_DEAD);
|
|
p_target->Genus.Person->Action=ACTION_DEAD;
|
|
p_target->Genus.Person->Timer1 = 0;
|
|
|
|
switch(p_person->Genus.Person->PersonType)
|
|
{
|
|
case PERSON_DARCI:
|
|
#ifndef PSX
|
|
MFX_play_thing(THING_NUMBER(p_person),SOUND_Range(S_DARCI_ARREST_START,S_DARCI_ARREST_END),MFX_MOVING|MFX_OVERLAP,p_person);
|
|
#else
|
|
MFX_play_thing(THING_NUMBER(p_person),S_DARCI_ARREST,MFX_MOVING|MFX_OVERLAP,p_person);
|
|
#endif
|
|
break;
|
|
#ifdef ROPER_EVER_ARRESTS_AGAIN
|
|
case PERSON_ROPER:
|
|
MFX_play_thing(THING_NUMBER(p_person),S_ROPER_ARREST,MFX_MOVING|MFX_OVERLAP,p_person);
|
|
break;
|
|
#endif
|
|
case PERSON_COP:
|
|
#ifndef PSX
|
|
MFX_play_thing(THING_NUMBER(p_person),SOUND_Range(S_COP_ARREST_START,S_COP_ARREST_END),MFX_MOVING|MFX_OVERLAP,p_person);
|
|
#else
|
|
// MFX_play_thing(THING_NUMBER(p_person),S_COP_ARREST_START,MFX_MOVING|MFX_OVERLAP,p_person);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Alert the world.
|
|
//
|
|
|
|
PCOM_oscillate_tympanum(
|
|
PCOM_SOUND_HEY,
|
|
p_person,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
}
|
|
|
|
}
|
|
|
|
void set_person_croutch(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
SLONG index;
|
|
|
|
if(p_person->Genus.Person->PersonType==PERSON_DARCI && (index=find_arrestee(p_person)))
|
|
{
|
|
// ASSERT(0);
|
|
set_person_arrest(p_person,index);
|
|
return;
|
|
}
|
|
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
if(person_has_gun_out(p_person))
|
|
{
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
anim = ANIM_SHOTGUN_DUCK;
|
|
}
|
|
else
|
|
{
|
|
anim = ANIM_PISTOL_DUCK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
anim = ANIM_CROUTCH_DOWN;
|
|
}
|
|
|
|
|
|
if(anim)
|
|
{
|
|
//
|
|
// Doing a locked anim change here makes Roper move backwards.
|
|
//
|
|
|
|
p_person->Draw.Tweened->Locked=0;
|
|
|
|
//locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim);
|
|
|
|
set_anim(p_person, anim);
|
|
|
|
p_person->Genus.Person->CombatNode=0;
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_CROUTCH;
|
|
p_person->SubState=SUB_STATE_IDLE_CROUTCH;
|
|
|
|
p_person->Draw.Tweened->Locked=0; //-SUB_OBJECT_LEFT_FOOT;
|
|
// p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
}
|
|
}
|
|
|
|
|
|
void set_person_crawling(Thing *p_person)
|
|
{
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
|
|
if(person_has_gun_out(p_person))
|
|
{
|
|
//
|
|
// Make sure this person isn't too near a fence.
|
|
//
|
|
|
|
|
|
SLONG x1 = p_person->WorldPos.X;
|
|
SLONG y1 = p_person->WorldPos.Y;
|
|
SLONG z1 = p_person->WorldPos.Z;
|
|
|
|
SLONG x2 = p_person->WorldPos.X;
|
|
SLONG y2 = p_person->WorldPos.Y;
|
|
SLONG z2 = p_person->WorldPos.Z;
|
|
|
|
slide_along(
|
|
x1, y1, z2,
|
|
&x2, &y2, &z2,
|
|
0,
|
|
50,
|
|
0);
|
|
|
|
GameCoord newpos;
|
|
|
|
newpos.X = x2;
|
|
newpos.Y = y2;
|
|
newpos.Z = z2;
|
|
|
|
move_thing_on_map(p_person, &newpos);
|
|
|
|
//
|
|
// Sniper crawl anim.
|
|
//
|
|
|
|
p_person->Draw.Tweened->Locked=0;
|
|
|
|
locked_anim_change(p_person,SUB_OBJECT_PELVIS,ANIM_SNIPER_CRAWL);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Normal crawl anim.
|
|
//
|
|
|
|
p_person->Draw.Tweened->Locked=0;
|
|
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_CRAWL);
|
|
}
|
|
|
|
p_person->Genus.Person->CombatNode=0;
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_CRAWLING;
|
|
p_person->SubState=SUB_STATE_CRAWLING; //_CROUTCH;
|
|
|
|
p_person->Draw.Tweened->Locked=0; //-SUB_OBJECT_LEFT_FOOT;
|
|
}
|
|
|
|
SLONG set_person_leg_sweep(Thing *p_person)
|
|
{
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
set_anim(p_person,ANIM_LEG_SWEEP);
|
|
|
|
p_person->Genus.Person->CombatNode = 0;
|
|
p_person->SubState = SUB_STATE_KICK;
|
|
return(0);
|
|
}
|
|
|
|
//
|
|
// this should only happen from fight idle or stand idle?
|
|
//
|
|
SLONG set_person_punch(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
SLONG node = 1;
|
|
// ASSERT(p_person->Genus.Person->PersonType!=PERSON_DARCI);
|
|
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_REQUEST_PUNCH;
|
|
|
|
if (!p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// For non-player characters. If the player is in a cut scene then
|
|
// it is a bit unfair to punch them!
|
|
//
|
|
|
|
UWORD i_target = PCOM_person_wants_to_kill(p_person);
|
|
|
|
if (i_target)
|
|
{
|
|
Thing *p_target = TO_THING(i_target);
|
|
|
|
if (dont_hurt_target_during_cutscene(p_person, p_target))
|
|
{
|
|
//
|
|
// Don't punch.
|
|
//
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
camera_fight();
|
|
}
|
|
*/
|
|
//
|
|
// if players punching while stepping forward or AI 1 in 4
|
|
//
|
|
|
|
// if((p_person->Genus.Person->PlayerID && p_person->SubState==SUB_STATE_STEP_FORWARD && p_person->Draw.Tweened->FrameIndex<2) || ((!p_person->Genus.Person->PlayerID) && ((GAME_TURN+THING_NUMBER(p_person))&0x3)==0))
|
|
if(find_best_grapple(p_person))
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
|
|
// anim=find_best_punch(p_person,FIND_BEST_USE_DEFAULT);
|
|
// anim=ANIM_PUNCH_COMBO1;
|
|
// p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][anim];
|
|
// p_person->Draw.Tweened->CurrentAnim = anim;
|
|
|
|
//
|
|
// What anim shall we use?
|
|
//
|
|
|
|
anim = ANIM_PUNCH_COMBO1;
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special;
|
|
|
|
//
|
|
// This person is using an item.
|
|
//
|
|
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
switch(p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_KNIFE:
|
|
anim=ANIM_KNIFE_ATTACK1;
|
|
node=14;
|
|
|
|
break;
|
|
|
|
case SPECIAL_BASEBALLBAT:
|
|
|
|
anim = ANIM_BAT_HIT1; break;
|
|
node=19;
|
|
/*
|
|
switch((Random() >> 4) & 1)
|
|
{
|
|
case 0: anim = ANIM_BAT_HIT1; break;
|
|
case 1: anim = ANIM_BAT_HIT2; break;
|
|
}
|
|
*/
|
|
|
|
break;
|
|
case SPECIAL_SHOTGUN:
|
|
case SPECIAL_AK47:
|
|
switch((Random() >> 4) & 1)
|
|
{
|
|
case 0: anim = ANIM_SHOTGUN_WHIP1; break;
|
|
case 1: anim = ANIM_SHOTGUN_WHIP2; break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (anim)
|
|
{
|
|
if (anim == ANIM_PUNCH_COMBO1 && p_person == NET_PERSON(0))
|
|
{
|
|
//
|
|
// Darci has done a punch
|
|
//
|
|
|
|
EWAY_darci_move |= EWAY_DARCI_MOVE_PUNCH;
|
|
}
|
|
|
|
p_person->Draw.Tweened->Locked = 0;
|
|
|
|
//locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim); //was pelvis, but pelvis is bobbing in fight idle
|
|
|
|
set_anim(p_person, anim);
|
|
|
|
p_person->Genus.Person->CombatNode = node;
|
|
p_person->Velocity = 0;
|
|
p_person->Genus.Person->Action = ACTION_FIGHT_PUNCH;
|
|
p_person->SubState = SUB_STATE_PUNCH;
|
|
|
|
p_person->Draw.Tweened->Locked = 0; //-SUB_OBJECT_LEFT_FOOT;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
}
|
|
|
|
// PlaySample(6);
|
|
return(anim);
|
|
}
|
|
|
|
#ifdef UNUSED
|
|
SLONG set_person_punch_if_can(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
/*
|
|
if(find_best_grapple(p_person))
|
|
{
|
|
return(0);
|
|
}
|
|
*/
|
|
anim=find_best_punch(p_person,0);
|
|
if(anim)
|
|
{
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
// p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][anim];
|
|
// p_person->Draw.Tweened->CurrentAnim = anim;
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim);
|
|
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_FIGHT_PUNCH;
|
|
p_person->SubState=SUB_STATE_PUNCH;
|
|
|
|
p_person->Draw.Tweened->Locked=0; //-SUB_OBJECT_LEFT_FOOT;
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
return(1);
|
|
}
|
|
return(0);
|
|
// PlaySample(6);
|
|
}
|
|
#endif
|
|
SLONG set_person_kick_dir(Thing *p_person,SLONG dir)
|
|
{
|
|
SLONG anim;
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_REQUEST_KICK;
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
camera_fight();
|
|
}
|
|
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
|
|
|
|
//
|
|
// What anim shall we use?
|
|
//
|
|
anim=ANIM_KICK_COMBO1;
|
|
|
|
switch(dir)
|
|
{
|
|
case 0: //n
|
|
break;
|
|
case 1: //e
|
|
anim=ANIM_KICK_RIGHT;
|
|
break;
|
|
case 2: //s
|
|
anim=ANIM_KICK_BEHIND;
|
|
break;
|
|
|
|
case 3: //w
|
|
anim=ANIM_KICK_LEFT;
|
|
break;
|
|
|
|
}
|
|
|
|
if (p_person == NET_PERSON(0))
|
|
{
|
|
EWAY_darci_move |= EWAY_DARCI_MOVE_KICK;
|
|
}
|
|
|
|
if (anim)
|
|
{
|
|
p_person->Draw.Tweened->Locked = 0;
|
|
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim); //was pelvis, but pelvis is bobbing in fight idle
|
|
|
|
p_person->Genus.Person->CombatNode = 1;
|
|
p_person->Velocity = 0;
|
|
p_person->Genus.Person->Action = ACTION_FIGHT_PUNCH;
|
|
p_person->SubState = SUB_STATE_KICK;
|
|
|
|
p_person->Draw.Tweened->Locked = 0; //-SUB_OBJECT_LEFT_FOOT;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
}
|
|
|
|
return(anim);
|
|
}
|
|
void set_person_fight_anim(Thing *p_person,SLONG anim)
|
|
{
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_REQUEST_KICK;
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_REQUEST_PUNCH;
|
|
|
|
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
|
|
if (anim)
|
|
{
|
|
p_person->Draw.Tweened->Locked = 0;
|
|
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim); //was pelvis, but pelvis is bobbing in fight idle
|
|
|
|
p_person->Genus.Person->CombatNode = 1;
|
|
p_person->Velocity = 0;
|
|
p_person->Genus.Person->Action = ACTION_FIGHT_PUNCH;
|
|
p_person->SubState = SUB_STATE_KICK;
|
|
|
|
p_person->Draw.Tweened->Locked = 0; //-SUB_OBJECT_LEFT_FOOT;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
}
|
|
|
|
}
|
|
/*
|
|
void set_person_alive_alive_o(Thing *p_person)
|
|
{
|
|
{
|
|
SLONG ndx=p_person->Genus.Person->BurnIndex;
|
|
Pyro *pyro;
|
|
|
|
set_person_idle(p_person);
|
|
plant_feet(p_person);
|
|
|
|
p_person->Genus.Person->Health=health[p_person->Genus.Person->PersonType];
|
|
if (ndx&&((pyro=TO_PYRO(ndx-1))->PyroType==PYRO_IMMOLATE)) {
|
|
pyro->Dummy=2;
|
|
pyro->radius=290;
|
|
}
|
|
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_KO | FLAG_PERSON_HELPLESS);
|
|
if(!CNET_network_game)
|
|
{
|
|
extern void FC_unkill_player_cam(Thing *p_thing);
|
|
FC_unkill_player_cam(p_person);
|
|
}
|
|
// set_anim(p_person,ANIM_STAND_HIP);
|
|
}
|
|
}
|
|
*/
|
|
SLONG set_person_kick(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_REQUEST_KICK;
|
|
|
|
if (!p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// For non-player characters. If the player is in a cut scene then
|
|
// it is a bit unfair to punch them!
|
|
//
|
|
|
|
UWORD i_target = PCOM_person_wants_to_kill(p_person);
|
|
|
|
if (i_target)
|
|
{
|
|
Thing *p_target = TO_THING(i_target);
|
|
|
|
if (dont_hurt_target_during_cutscene(p_person, p_target))
|
|
{
|
|
//
|
|
// Don't kick.
|
|
//
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_person == NET_PERSON(0))
|
|
{
|
|
EWAY_darci_move |= EWAY_DARCI_MOVE_KICK;
|
|
}
|
|
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
// anim=find_best_kick(p_person, FIND_BEST_USE_DEFAULT);
|
|
|
|
anim=ANIM_KICK_COMBO1;
|
|
p_person->Draw.Tweened->Locked=0;
|
|
p_person->Genus.Person->CombatNode=6;
|
|
|
|
//locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim);
|
|
set_anim(p_person,anim);
|
|
|
|
/*
|
|
p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_KICK_ROUND1];
|
|
p_person->Draw.Tweened->CurrentAnim = ANIM_KICK_ROUND1;
|
|
*/
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_FIGHT_PUNCH;
|
|
p_person->SubState=SUB_STATE_KICK;
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
return(anim);
|
|
|
|
}
|
|
|
|
SLONG set_person_kick_near(Thing *p_person,SLONG dist)
|
|
{
|
|
SLONG anim;
|
|
SLONG not_nad=0;
|
|
|
|
if (p_person == NET_PERSON(0))
|
|
{
|
|
EWAY_darci_move |= EWAY_DARCI_MOVE_KICK;
|
|
}
|
|
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_REQUEST_KICK;
|
|
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
|
|
if(p_person->Genus.Person->Target)
|
|
{
|
|
Thing *p_victim;
|
|
p_victim=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
if(p_victim->Draw.Tweened->CurrentAnim==ANIM_KICK_NAD_TAKE || p_victim->Draw.Tweened->CurrentAnim==ANIM_KICK_NAD_STUNNED || p_victim->Draw.Tweened->CurrentAnim==ANIM_KICK_NAD_RECOVER)
|
|
not_nad=1;
|
|
|
|
}
|
|
if(p_person->Genus.Person->PersonType==PERSON_DARCI && dist<100 && p_person->SubState==SUB_STATE_STEP_FORWARD && !not_nad)
|
|
anim=ANIM_KICK_NAD;
|
|
else
|
|
anim=ANIM_KICK_NEAR;
|
|
p_person->Draw.Tweened->Locked=0;
|
|
p_person->Genus.Person->CombatNode=0;
|
|
|
|
if(p_person->SubState==SUB_STATE_STEP_FORWARD)
|
|
set_anim(p_person,anim);
|
|
else
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim);
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_FIGHT_PUNCH;
|
|
p_person->SubState=SUB_STATE_KICK;
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
return(anim);
|
|
|
|
}
|
|
|
|
SLONG set_person_stomp(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_REQUEST_KICK;
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
camera_fight();
|
|
}
|
|
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
|
|
anim=ANIM_FIGHT_STOMP;
|
|
p_person->Draw.Tweened->Locked=0;
|
|
p_person->Genus.Person->CombatNode=0;
|
|
|
|
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim);
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_FIGHT_PUNCH;
|
|
p_person->SubState=SUB_STATE_KICK;
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
return(anim);
|
|
|
|
}
|
|
|
|
void set_person_position_for_ladder(Thing *p_person,UWORD facet)
|
|
{
|
|
SLONG angle,px,pz;
|
|
GameCoord new_position;
|
|
SLONG scale=256;
|
|
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
scale=320;
|
|
|
|
|
|
correct_pos_for_ladder(&dfacets[facet],&px,&pz,&angle,scale);
|
|
|
|
new_position.X =px<<8;
|
|
new_position.Y =p_person->WorldPos.Y;
|
|
new_position.Z =pz<<8;
|
|
|
|
p_person->Draw.Tweened->Angle=angle;
|
|
|
|
move_thing_on_map(p_person,&new_position);
|
|
|
|
/*
|
|
|
|
if(p_person->Genus.Person->PlayerID==PLAYER_ID+1)
|
|
{
|
|
correct_pos_for_ladder(storey,&px,&pz,&angle,15);
|
|
|
|
new_position.X =px<<8;
|
|
new_position.Y =(p_person->WorldPos.Y+(200<<8));
|
|
new_position.Z =pz<<8;
|
|
}
|
|
*/
|
|
}
|
|
|
|
inline void play_jump_sound(Thing *p_person) {
|
|
static SLONG jump_chan=0;
|
|
SLONG jump_snd=0;
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
if (p_person->Flags & FLAGS_IN_SEWERS) {
|
|
switch (person_is_on_sewer(p_person)) {
|
|
case PERSON_ON_SEWATER:
|
|
jump_snd=S_CLIMB_SEWER; break;
|
|
case PERSON_ON_WATER:
|
|
jump_snd=S_FOOTS_PUDDLE_START; break;
|
|
}
|
|
}
|
|
#endif
|
|
// if (jump_snd) jump_chan=play_quick_wave_xyz(p_person->WorldPos.X,p_person->WorldPos.Y,p_person->WorldPos.Z,jump_snd,jump_chan,WAVE_PLAY_NO_INTERRUPT);
|
|
// if (jump_snd) play_quick_wave_xyz(p_person->WorldPos.X,p_person->WorldPos.Y,p_person->WorldPos.Z,jump_snd,jump_chan,WAVE_PLAY_NO_INTERRUPT);
|
|
if (jump_snd) MFX_play_thing(THING_NUMBER(p_person),jump_snd,0,p_person);
|
|
}
|
|
|
|
|
|
void set_person_climb_ladder(Thing *p_person,UWORD storey)
|
|
{
|
|
// MSG_add(" set person climb ladder \n");
|
|
set_generic_person_state_function(p_person,STATE_CLIMB_LADDER);
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
{
|
|
set_anim_of_type(p_person,COP_ROPER_ANIM_LADDER_START,ANIM_TYPE_ROPER);
|
|
}
|
|
else
|
|
// if(p_person->Genus.Person->PersonType==PERSON_COP)
|
|
if(p_person->Genus.Person->PersonType==PERSON_COP||p_person->Genus.Person->PersonType==PERSON_THUG_GREY||p_person->Genus.Person->PersonType==PERSON_THUG_RASTA||p_person->Genus.Person->PersonType==PERSON_THUG_RED)
|
|
{
|
|
set_anim_of_type(p_person,COP_ROPER_ANIM_LADDER_START,ANIM_TYPE_ROPER);
|
|
}
|
|
else
|
|
{
|
|
set_anim(p_person,ANIM_MOUNT_LADDER);
|
|
}
|
|
|
|
/*
|
|
p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_MOUNT_LADDER];
|
|
p_person->Draw.Tweened->CurrentAnim = ANIM_MOUNT_LADDER;
|
|
*/
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_CLIMBING;
|
|
p_person->SubState=SUB_STATE_MOUNT_LADDER;
|
|
p_person->Genus.Person->OnFacet=storey;
|
|
set_person_position_for_ladder(p_person,storey);
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C;
|
|
|
|
play_jump_sound(p_person);
|
|
|
|
}
|
|
void set_person_on_ladder(Thing *p_person)
|
|
{
|
|
// set_generic_person_state_function(p_person,STATE_CLIMB_LADDER);
|
|
// MSG_add(" set person ON ladder \n");
|
|
// set_anim(p_person,ANIM_ON_LADDER);
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
{
|
|
locked_anim_change_of_type(p_person,0,COP_ROPER_ANIM_LADDER_LOOP,ANIM_TYPE_ROPER);
|
|
}
|
|
else
|
|
// if(p_person->Genus.Person->PersonType==PERSON_COP)
|
|
if(p_person->Genus.Person->PersonType==PERSON_COP||p_person->Genus.Person->PersonType==PERSON_THUG_GREY||p_person->Genus.Person->PersonType==PERSON_THUG_RASTA||p_person->Genus.Person->PersonType==PERSON_THUG_RED)
|
|
{
|
|
locked_anim_change_of_type(p_person,0,COP_ROPER_ANIM_LADDER_LOOP,ANIM_TYPE_ROPER);
|
|
}
|
|
else
|
|
{
|
|
locked_anim_change(p_person,0,ANIM_ON_LADDER);
|
|
}
|
|
|
|
//
|
|
// Make sure they aren't doing fighting controls.
|
|
//
|
|
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
|
|
/*
|
|
p_person->Draw.Tweened->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_ON_LADDER];
|
|
p_person->Draw.Tweened->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_ON_LADDER]->NextFrame;
|
|
*/
|
|
p_person->Draw.Tweened->AnimTween = 0; //global_anim_array[p_person->Genus.Person->AnimType][ANIM_ON_LADDER]->NextFrame;
|
|
p_person->Velocity=0;
|
|
p_person->SubState=SUB_STATE_ON_LADDER;
|
|
p_person->Genus.Person->Action=ACTION_CLIMBING;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M);
|
|
p_person->OnFace = NULL;
|
|
|
|
}
|
|
|
|
void set_person_on_fence(Thing *p_person)
|
|
{
|
|
|
|
// set_generic_person_state_function(p_person,STATE_CLIMB_LADDER);
|
|
// MSG_add(" set person ON ladder \n");
|
|
set_anim(p_person,ANIM_CLIMB_UP_FENCE);
|
|
/* p_person->Draw.Tweened->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_CLIMB_UP_FENCE];
|
|
p_person->Draw.Tweened->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_CLIMB_UP_FENCE]->NextFrame;
|
|
*/
|
|
p_person->Draw.Tweened->AnimTween = 0; //global_anim_array[p_person->Genus.Person->AnimType][ANIM_ON_LADDER]->NextFrame;
|
|
p_person->Velocity=0;
|
|
p_person->SubState=SUB_STATE_CLIMB_AROUND_WALL;
|
|
p_person->Genus.Person->Action=ACTION_CLIMBING;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
p_person->OnFace = NULL;
|
|
}
|
|
|
|
|
|
void set_person_standing_jump(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
if(p_person->Genus.Person->InsideIndex)
|
|
return;
|
|
if(p_person->SubState==SUB_STATE_SLIPPING)
|
|
return;
|
|
|
|
//
|
|
// Is this person standing in front of a climbable fence? If so
|
|
// don't do a standing jump. Climb onto the fence.
|
|
//
|
|
|
|
{
|
|
SLONG x1;
|
|
SLONG y1;
|
|
SLONG z1;
|
|
|
|
SLONG x2;
|
|
SLONG y2;
|
|
SLONG z2;
|
|
|
|
SLONG dx = -SIN(p_person->Draw.Tweened->Angle) >> 2;
|
|
SLONG dz = -COS(p_person->Draw.Tweened->Angle) >> 2;
|
|
|
|
x1 = p_person->WorldPos.X >> 8;
|
|
y1 = p_person->WorldPos.Y + 0xa000 >> 8;
|
|
z1 = p_person->WorldPos.Z >> 8;
|
|
|
|
x2 = p_person->WorldPos.X + dx >> 8;
|
|
y2 = p_person->WorldPos.Y + 0xa000 >> 8;
|
|
z2 = p_person->WorldPos.Z + dz >> 8;
|
|
|
|
if (!there_is_a_los(
|
|
x1, y1, z1,
|
|
x2, y2, z2,
|
|
LOS_FLAG_IGNORE_SEETHROUGH_FENCE_FLAG |
|
|
LOS_FLAG_IGNORE_PRIMS |
|
|
LOS_FLAG_IGNORE_UNDERGROUND_CHECK))
|
|
{
|
|
if (los_failure_dfacet)
|
|
{
|
|
DFacet *df;
|
|
|
|
df = &dfacets[los_failure_dfacet];
|
|
|
|
if (df->FacetType == STOREY_TYPE_FENCE ||
|
|
df->FacetType == STOREY_TYPE_FENCE_FLAT ||
|
|
df->FacetType == STOREY_TYPE_FENCE_BRICK)
|
|
{
|
|
if (!(df->FacetFlags & FACET_FLAG_UNCLIMBABLE))
|
|
{
|
|
//
|
|
// The person is standing in front of a climbable fence.
|
|
//
|
|
|
|
set_person_land_on_fence(p_person, los_failure_dfacet, 1);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(person_holding_2handed(p_person))
|
|
anim=ANIM_STANDING_JUMP_AK;
|
|
else
|
|
anim=ANIM_STANDING_JUMP;
|
|
|
|
set_generic_person_state_function(p_person,STATE_JUMPING);
|
|
set_anim(p_person,anim);
|
|
/*
|
|
p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_STANDING_JUMP];
|
|
p_person->Draw.Tweened->CurrentAnim = ANIM_STANDING_JUMP;
|
|
*/
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_STANDING_JUMP;
|
|
p_person->SubState=SUB_STATE_STANDING_JUMP;
|
|
// PlaySample(THING_NUMBER(p_person),SAMPLE_WOMAN_JUMP1,SAMPLE_VOL_MAX,SAMPLE_PAN_CENTER,SAMPLE_FREQ_ORIG+(GAME_TURN&0xfff),0);
|
|
play_jump_sound(p_person);
|
|
p_person->OnFace = 0;
|
|
}
|
|
|
|
void set_person_standing_jump_forwards(Thing *p_person)
|
|
{
|
|
SLONG slope;
|
|
SLONG angle;
|
|
if(p_person->OnFace<0)
|
|
{
|
|
slope=RFACE_on_slope(-p_person->OnFace,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle);
|
|
}
|
|
else
|
|
{
|
|
|
|
slope=PAP_on_slope(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle)>>1;
|
|
}
|
|
if(slope>50)
|
|
return;
|
|
|
|
|
|
if(p_person->Genus.Person->InsideIndex)
|
|
return;
|
|
if(p_person->SubState==SUB_STATE_SLIPPING)
|
|
return;
|
|
set_person_running_jump(p_person);
|
|
/*
|
|
set_generic_person_state_function(p_person,STATE_JUMPING);
|
|
set_anim(p_person,ANIM_FORWARD_JUMP);
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_STANDING_JUMP;
|
|
p_person->SubState=SUB_STATE_STANDING_JUMP_FORWARDS;
|
|
// PlaySample(THING_NUMBER(p_person),SAMPLE_WOMAN_JUMP1,SAMPLE_VOL_MAX,SAMPLE_PAN_CENTER,SAMPLE_FREQ_ORIG+(GAME_TURN&0xfff),0);
|
|
play_jump_sound(p_person);
|
|
p_person->OnFace = 0;
|
|
*/
|
|
}
|
|
|
|
void set_person_standing_jump_backwards(Thing *p_person)
|
|
{
|
|
SLONG slope;
|
|
SLONG angle;
|
|
if(p_person->OnFace<0)
|
|
{
|
|
slope=RFACE_on_slope(-p_person->OnFace,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle);
|
|
}
|
|
else
|
|
{
|
|
|
|
slope=PAP_on_slope(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle)>>1;
|
|
}
|
|
if(slope>50)
|
|
return;
|
|
|
|
if(p_person->Genus.Person->InsideIndex)
|
|
return;
|
|
if(p_person->SubState==SUB_STATE_SLIPPING)
|
|
return;
|
|
set_person_running_jump(p_person);
|
|
|
|
set_generic_person_state_function(p_person,STATE_JUMPING);
|
|
set_anim(p_person,ANIM_BACK_FLIP);
|
|
p_person->Velocity=0;
|
|
p_person->Genus.Person->Action=ACTION_STANDING_JUMP;
|
|
p_person->SubState=SUB_STATE_STANDING_JUMP_BACKWARDS;
|
|
// PlaySample(THING_NUMBER(p_person),SAMPLE_WOMAN_JUMP1,SAMPLE_VOL_MAX,SAMPLE_PAN_CENTER,SAMPLE_FREQ_ORIG+(GAME_TURN&0xfff),0);
|
|
play_jump_sound(p_person);
|
|
p_person->OnFace = 0;
|
|
|
|
}
|
|
|
|
void set_person_running_jump_lr(Thing *p_person,SLONG dir);
|
|
|
|
void set_person_running_jump(Thing *p_person)
|
|
{
|
|
SLONG slope;
|
|
SLONG angle;
|
|
if(p_person->OnFace<0)
|
|
{
|
|
slope=RFACE_on_slope(-p_person->OnFace,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle);
|
|
}
|
|
else
|
|
{
|
|
|
|
slope=PAP_on_slope(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle)>>1;
|
|
}
|
|
if(slope>50)
|
|
return;
|
|
|
|
if(p_person->SubState==SUB_STATE_SLIPPING || p_person->Genus.Person->InsideIndex)
|
|
return;
|
|
|
|
/*
|
|
p_person->SubState=SUB_STATE_RUNNING_THEN_JUMP;
|
|
|
|
set_person_running_jump_lr(p_person,1);
|
|
switch(p_person->Draw.Tweened->FrameIndex)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
set_person_running_jump_lr(p_person,1);
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
set_person_running_jump_lr(p_person,0);
|
|
break;
|
|
}
|
|
*/
|
|
|
|
set_generic_person_state_function(p_person,STATE_JUMPING);
|
|
if(person_has_gun_out(p_person))
|
|
{
|
|
set_anim(p_person,ANIM_RUN_JUMP_LEFT_AK);
|
|
}
|
|
else
|
|
{
|
|
set_anim(p_person,ANIM_RUN_JUMP_LEFT);
|
|
}
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
if (p_person->Velocity < 16)
|
|
{
|
|
p_person->Velocity = 16;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p_person->Velocity = PCOM_if_i_wanted_to_jump_how_fast_should_i_do_it(p_person);
|
|
}
|
|
|
|
p_person->DY=0;
|
|
p_person->DY=10<<8;
|
|
p_person->Genus.Person->Action=ACTION_RUNNING_JUMP;
|
|
p_person->SubState=SUB_STATE_RUNNING_JUMP;
|
|
p_person->OnFace = 0;
|
|
|
|
play_jump_sound(p_person);
|
|
|
|
}
|
|
|
|
void set_person_running_jump_lr(Thing *p_person,SLONG dir)
|
|
{
|
|
}
|
|
|
|
SLONG traverse_pos(Thing *p_person,SLONG right)
|
|
{
|
|
SLONG lhx,lhy,lhz;
|
|
// SLONG rhx,rhy,rhz;
|
|
SLONG angle;
|
|
SLONG grab_x,grab_y,grab_z,type;
|
|
SLONG x,y,z;
|
|
SLONG face,grab_angle;
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,SUB_OBJECT_LEFT_HAND, &lhx,&lhy,&lhz);
|
|
// calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,SUB_OBJECT_RIGHT_HAND,&rhx,&rhy,&rhz);
|
|
|
|
x = lhx + (p_person->WorldPos.X >> 8);
|
|
y = lhy + (p_person->WorldPos.Y >> 8);
|
|
z = lhz + (p_person->WorldPos.Z >> 8);
|
|
|
|
if(right)
|
|
{
|
|
angle=(p_person->Draw.Tweened->Angle-512)&2047;
|
|
|
|
}
|
|
else
|
|
{
|
|
angle=(p_person->Draw.Tweened->Angle+512)&2047;
|
|
|
|
}
|
|
|
|
x+=-(SIN(angle)*74)>>16; //precit hand pos at end of sideways movement
|
|
z+=-(COS(angle)*74)>>16;
|
|
|
|
//
|
|
// If this square is too near a nogo zone or underground...
|
|
//
|
|
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG cx;
|
|
SLONG cz;
|
|
|
|
for (dx = -32; dx <= 32; dx += 32)
|
|
for (dz = -32; dz <= 32; dz += 32)
|
|
{
|
|
cx = x + dx;
|
|
cz = z + dz;
|
|
|
|
if (!WITHIN(cx >> 8, 0, PAP_SIZE_HI - 1) ||
|
|
!WITHIN(cz >> 8, 0, PAP_SIZE_HI - 1))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// if this place is underground...
|
|
//
|
|
|
|
if (PAP_calc_map_height_at(cx,cz) > y + 0x30)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
cx >>= 8;
|
|
cz >>= 8;
|
|
|
|
if (PAP_2HI(cx,cz).Flags & PAP_FLAG_NOGO)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// check to see if face available for hands to grab at end of sideways movement
|
|
//
|
|
face = find_grab_face(
|
|
x,y,z,
|
|
20,40, //strict on radius
|
|
p_person->Draw.Tweened->Angle,
|
|
&grab_x,
|
|
&grab_y,
|
|
&grab_z,
|
|
&grab_angle,
|
|
0,
|
|
0,&type,
|
|
p_person);
|
|
|
|
if(face==0)
|
|
return(0);
|
|
|
|
if(type!=0)
|
|
return(0); //ladder or cable, or other odd thing found
|
|
|
|
{
|
|
SLONG new_x,new_y,new_z;
|
|
GameCoord temp_pos;
|
|
|
|
x-=-(SIN(angle)*74)>>16; //get hand pos back to start of traverse
|
|
z-=-(COS(angle)*74)>>16;
|
|
|
|
//
|
|
// reposition self as repeating traverse anim is not good enough to make you move along straight line
|
|
//
|
|
face = find_grab_face(
|
|
x,y,z,
|
|
20,40,
|
|
p_person->Draw.Tweened->Angle,
|
|
&grab_x,
|
|
&grab_y,
|
|
&grab_z,
|
|
&grab_angle,
|
|
0,
|
|
0,&type,
|
|
p_person);
|
|
|
|
if(face==0)
|
|
{
|
|
return(1); //dont repos
|
|
ASSERT(0);
|
|
}
|
|
|
|
|
|
|
|
calc_sub_objects_position(p_person,0,SUB_OBJECT_LEFT_HAND,&new_x,&new_y,&new_z);
|
|
|
|
new_x+=p_person->WorldPos.X>>8;
|
|
new_y+=p_person->WorldPos.Y>>8;
|
|
new_z+=p_person->WorldPos.Z>>8;
|
|
|
|
// MSG_add(" left hand y %d grab_y %d tween %d\n",new_y,grab_y,draw_info->AnimTween);
|
|
|
|
//LogText(" left hand pos for grab face after anim change %d %d %d \n",new_x,new_y,new_z);
|
|
|
|
//LogText(" found a ledge offset %d %d %d to it \n",grab_x-new_x,grab_y-new_y,grab_z-new_z);
|
|
|
|
temp_pos.X=((grab_x-new_x)<<8)+p_person->WorldPos.X;
|
|
temp_pos.Y=((grab_y-new_y)<<8)+p_person->WorldPos.Y;
|
|
temp_pos.Z=((grab_z-new_z)<<8)+p_person->WorldPos.Z;
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
|
|
void set_person_traverse(Thing *p_person,SLONG right)
|
|
{
|
|
if(traverse_pos(p_person,right)==0)
|
|
return;
|
|
|
|
set_generic_person_state_function(p_person,STATE_DANGLING); //should allready be in this state
|
|
if(right)
|
|
{
|
|
|
|
p_person->SubState=SUB_STATE_TRAVERSE_RIGHT;
|
|
p_person->Genus.Person->Action=ACTION_TRAVERSE_RIGHT;
|
|
set_locked_anim(p_person,ANIM_TRAVERSE_RIGHT,0);
|
|
}
|
|
else
|
|
{
|
|
p_person->SubState=SUB_STATE_TRAVERSE_LEFT;
|
|
p_person->Genus.Person->Action=ACTION_TRAVERSE_LEFT;
|
|
set_locked_anim(p_person,ANIM_TRAVERSE_LEFT,0);
|
|
}
|
|
p_person->Draw.Tweened->Locked=0;
|
|
|
|
}
|
|
void set_person_pulling_up(Thing *p_person)
|
|
{
|
|
//
|
|
// Make sure the person won't pull-up into a nogo zone.
|
|
//
|
|
|
|
{
|
|
SLONG dx = -SIN(p_person->Draw.Tweened->Angle) >> 2;
|
|
SLONG dz = -COS(p_person->Draw.Tweened->Angle) >> 2;
|
|
|
|
SLONG mx = p_person->WorldPos.X + dx >> 16;
|
|
SLONG mz = p_person->WorldPos.Z + dz >> 16;
|
|
|
|
if (!WITHIN(mx, 0, PAP_SIZE_HI - 1) ||
|
|
!WITHIN(mz, 0, PAP_SIZE_HI - 1))
|
|
{
|
|
//
|
|
// Pull up off the map!
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
if (PAP_2HI(mx,mz).Flags & PAP_FLAG_NOGO)
|
|
{
|
|
//
|
|
// Pull up into a nogo area!
|
|
//
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
set_generic_person_state_function(p_person,STATE_DANGLING); //should allready be in this state
|
|
p_person->SubState=SUB_STATE_PULL_UP;
|
|
// queue_anim(p_person,ANIM_PULL_UP_NEW);
|
|
set_locked_anim(p_person,ANIM_PULL_UP_NEW,0);
|
|
/*
|
|
p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_PULL_UP];
|
|
p_person->Draw.Tweened->CurrentAnim = ANIM_PULL_UP;*/
|
|
p_person->Genus.Person->Action=ACTION_PULL_UP;
|
|
p_person->Draw.Tweened->Locked=0;
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C;
|
|
|
|
}
|
|
|
|
extern void make_cable_flabby(SLONG building);
|
|
|
|
//
|
|
// Make a person start falling as a projectile...
|
|
//
|
|
|
|
void set_person_drop_down(Thing *p_person,SLONG flag)
|
|
{
|
|
SLONG dv=-2;
|
|
SLONG shotgun=0;
|
|
|
|
SlideSoundCheck(p_person,1);
|
|
|
|
if(person_holding_2handed(p_person))
|
|
shotgun=1;
|
|
MSG_add(" set person drop");
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_ON_CABLE;
|
|
MFX_stop(THING_NUMBER(p_person), S_ZIPWIRE);
|
|
if( p_person->State==STATE_DANGLING && (p_person->SubState==SUB_STATE_DANGLING_CABLE||p_person->SubState==SUB_STATE_DANGLING_CABLE_FORWARD||p_person->SubState==SUB_STATE_DANGLING_CABLE_BACKWARD) )
|
|
{
|
|
if(p_person->OnFace)
|
|
{
|
|
/*
|
|
if(prim_faces4[p_person->OnFace].Type==FACE_TYPE_CABLE)
|
|
{
|
|
SLONG wall,storey,building;
|
|
wall=-prim_faces4[p_person->OnFace].ThingIndex;
|
|
storey=wall_list[wall].StoreyHead;
|
|
|
|
building=storey_list[storey].BuildingHead;
|
|
make_cable_flabby(building);
|
|
dv=0;
|
|
|
|
}
|
|
*/
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_ON_CABLE)
|
|
{
|
|
// make_cable_flabby(building);
|
|
dv=0;
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
if( p_person->SubState==SUB_STATE_SLIPPING || p_person->SubState==SUB_STATE_SLIPPING_END)
|
|
{
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_MOVE_ANGLETO;
|
|
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_MOVE_ANGLETO;
|
|
}
|
|
|
|
set_generic_person_state_function(p_person,STATE_DANGLING);
|
|
|
|
if (flag & PERSON_DROP_DOWN_OFF_FACE)
|
|
{
|
|
p_person->SubState = SUB_STATE_DROP_DOWN_OFF_FACE;
|
|
}
|
|
else
|
|
{
|
|
p_person->SubState = SUB_STATE_DROP_DOWN;
|
|
}
|
|
|
|
// p_person->Draw.Tweened->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_FALLING];
|
|
// p_person->Draw.Tweened->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_FALLING]->NextFrame;
|
|
|
|
if (!(flag & PERSON_DROP_DOWN_QUEUED))
|
|
{
|
|
if(shotgun)
|
|
locked_anim_change(p_person,0,ANIM_FALLING_AK);
|
|
else
|
|
locked_anim_change(p_person,0,ANIM_FALLING);
|
|
}
|
|
else
|
|
{
|
|
if(shotgun)
|
|
queue_anim(p_person,ANIM_FALLING_QUEUED_AK);
|
|
else
|
|
queue_anim(p_person,ANIM_FALLING_QUEUED);
|
|
|
|
}
|
|
// p_person->Draw.Tweened->CurrentAnim = ANIM_FALLING;
|
|
p_person->Genus.Person->Action=ACTION_DROP_DOWN;
|
|
p_person->Draw.Tweened->AnimTween=0;
|
|
p_person->Draw.Tweened->Locked=0;
|
|
|
|
// if((flag&1)==0)
|
|
// p_person->Velocity=-8;
|
|
|
|
if (!(flag & PERSON_DROP_DOWN_KEEP_VEL))
|
|
{
|
|
p_person->Velocity = -8;
|
|
}
|
|
else
|
|
{
|
|
if(abs(p_person->Velocity)<8)
|
|
{
|
|
if(p_person->Velocity<0)
|
|
p_person->Velocity=-8;
|
|
else
|
|
p_person->Velocity=8;
|
|
}
|
|
}
|
|
|
|
p_person->DeltaVelocity=0;//dv;
|
|
|
|
// if((flag&4)==0)
|
|
// p_person->DY=-(4<<8);
|
|
|
|
if (!(flag & PERSON_DROP_DOWN_KEEP_DY))
|
|
{
|
|
p_person->DY = -(4 << 8);
|
|
}
|
|
|
|
p_person->OnFace=0;
|
|
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M;
|
|
|
|
}
|
|
|
|
void set_person_locked_drop_down(Thing *p_person,SLONG vely)
|
|
{
|
|
MSG_add(" set person drop locked");
|
|
set_generic_person_state_function(p_person,STATE_DANGLING);
|
|
p_person->SubState=SUB_STATE_DROP_DOWN;
|
|
locked_anim_change(p_person,0,ANIM_FALLING);
|
|
p_person->Genus.Person->Action=ACTION_DROP_DOWN;
|
|
p_person->Draw.Tweened->Locked=0;
|
|
p_person->Velocity=0;
|
|
p_person->DeltaVelocity=0;
|
|
p_person->DY=(vely<<8);
|
|
p_person->OnFace=0;
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M;
|
|
|
|
}
|
|
|
|
extern SLONG nearest_point_on_line_and_dist( SLONG x1, SLONG z1, SLONG x2, SLONG z2, SLONG a, SLONG b,SLONG *ret_x,SLONG *ret_z);
|
|
|
|
|
|
SLONG is_wall_good_for_bump_and_turn(Thing *p_person,SLONG col)
|
|
{
|
|
struct DFacet *p_facet;
|
|
|
|
|
|
SLONG dist,angle,wy,wx,wz;
|
|
SLONG mx,my,mz,dx,dz;
|
|
|
|
angle=p_person->Draw.Tweened->Angle;
|
|
|
|
wx=p_person->WorldPos.X>>8;
|
|
wy=p_person->WorldPos.Y>>8;
|
|
wz=p_person->WorldPos.Z>>8;
|
|
|
|
dx = -(SIN(angle)) >> 9;
|
|
dz = -(COS(angle)) >> 9;
|
|
|
|
mx=(wx+dx)>>8;
|
|
mz=(wz+dz)>>8;
|
|
|
|
|
|
my=MAVHEIGHT(mx,mz)<<6;
|
|
|
|
if(wy>my-196)
|
|
return(0);
|
|
|
|
return(1);
|
|
|
|
|
|
/*
|
|
p_facet=&dfacets[col];
|
|
|
|
if(p_facet->BlockHeight>8)
|
|
return(1);
|
|
else
|
|
return(0);
|
|
*/
|
|
|
|
}
|
|
|
|
//#define VAULT_DA 128
|
|
SLONG am_i_facing_wall(Thing *p_person,SLONG col,SLONG *wall_angle,SLONG vault_da=128)
|
|
{
|
|
SLONG mdx,mdz,dx,dz,len,dist;
|
|
SLONG near_x,near_z;
|
|
SLONG wx,wy,wz;
|
|
SLONG angle;
|
|
GameCoord new_position;
|
|
SLONG on,norm_x,norm_z;
|
|
struct DFacet *p_facet;
|
|
SLONG req_dist=50;
|
|
SLONG side;
|
|
|
|
p_facet=&dfacets[col];
|
|
|
|
dx = p_facet->x[1] - p_facet->x[0] << 8;
|
|
dz = p_facet->z[1] - p_facet->z[0] << 8;
|
|
/*
|
|
AENG_world_line(
|
|
p_facet->x[0]<<8,p_facet->Y[0],p_facet->z[0]<<8,
|
|
16,
|
|
0xff0000,
|
|
p_facet->x[1]<<8,p_facet->Y[0],p_facet->z[1]<<8,
|
|
0,
|
|
0x330088,
|
|
TRUE);
|
|
*/
|
|
|
|
mdx=abs(dx);
|
|
mdz=abs(dz);
|
|
|
|
|
|
{
|
|
SLONG da;
|
|
angle=Arctan(-dx,dz)-512; //+512;
|
|
if(angle<0)
|
|
angle=2048+angle;
|
|
angle=angle&2047;
|
|
*wall_angle=angle;
|
|
|
|
da = abs(angle - p_person->Draw.Tweened->Angle);
|
|
// PANEL_new_text(p_person,10000,"da %d",da);
|
|
|
|
// if((da>VAULT_DA && da <1024-VAULT_DA )||(da>1024+VAULT_DA && da <2048-VAULT_DA ))
|
|
|
|
if(p_facet->FacetType==STOREY_TYPE_FENCE ||p_facet->FacetType==STOREY_TYPE_FENCE_FLAT)
|
|
{
|
|
extern SLONG which_side(SLONG x1, SLONG z1,SLONG x2, SLONG z2,SLONG a, SLONG b);
|
|
|
|
if(which_side(p_facet->x[0]<<8,p_facet->z[0]<<8,p_facet->x[1]<<8,p_facet->z[1]<<8,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<0)
|
|
{
|
|
// on other side
|
|
da+=1024;
|
|
|
|
// da&=2047;
|
|
|
|
}
|
|
}
|
|
if((da<vault_da && da>-vault_da) || (da>2048-vault_da && da<2048+vault_da))
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
//
|
|
// hopefully this will work with diagonal fences, should they exist
|
|
//
|
|
SLONG along_middle_of_facet(Thing *p_person,SLONG col)
|
|
{
|
|
SLONG wx,wy,wz;
|
|
SLONG on,norm_x,norm_z,dist;
|
|
struct DFacet *p_facet;
|
|
|
|
//
|
|
// Along the middle of the facet?
|
|
//
|
|
|
|
p_facet=&dfacets[col];
|
|
|
|
wx = p_person->WorldPos.X >> 8;
|
|
wy = p_person->WorldPos.Y >> 8;
|
|
wz = p_person->WorldPos.Z >> 8;
|
|
|
|
signed_dist_to_line_with_normal(
|
|
p_facet->x[0] << 8, p_facet->z[0] << 8,
|
|
p_facet->x[1] << 8, p_facet->z[1] << 8,
|
|
wx, wz,
|
|
&dist,
|
|
&norm_x,
|
|
&norm_z,
|
|
&on);
|
|
|
|
if(on)
|
|
{
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
SLONG set_person_pos_for_fence_vault(Thing *p_person,SLONG col)
|
|
{
|
|
SLONG mdx,mdz,dx,dz,len,dist;
|
|
SLONG near_x,near_z;
|
|
SLONG wx,wy,wz;
|
|
SLONG angle;
|
|
GameCoord new_position;
|
|
SLONG on,norm_x,norm_z;
|
|
struct DFacet *p_facet;
|
|
SLONG req_dist=50;
|
|
SLONG side;
|
|
SLONG bot;
|
|
SLONG top;
|
|
|
|
//
|
|
// Is this person in the correct y for the fence.
|
|
//
|
|
|
|
bot = get_fence_bottom(p_person->WorldPos.X >> 8, p_person->WorldPos.Z >> 8, col);
|
|
top = get_fence_top (p_person->WorldPos.X >> 8, p_person->WorldPos.Z >> 8, col);
|
|
|
|
if (!WITHIN(p_person->WorldPos.Y >> 8, bot - 30, top))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
p_facet = &dfacets[col];
|
|
|
|
dx = p_facet->x[1] - p_facet->x[0] << 8;
|
|
dz = p_facet->z[1] - p_facet->z[0] << 8;
|
|
|
|
mdx=abs(dx);
|
|
mdz=abs(dz);
|
|
|
|
#undef VAULT_DA
|
|
#define VAULT_DA (p_person->Genus.Person->PlayerID ? 128 : 256)
|
|
|
|
{
|
|
SLONG da;
|
|
angle=Arctan(-mdx,mdz)+1024+512;
|
|
if(angle<0)
|
|
angle=2048+angle;
|
|
angle=angle&2047;
|
|
|
|
da = abs(angle - p_person->Draw.Tweened->Angle);
|
|
|
|
if((da>VAULT_DA && da <1024-VAULT_DA )||(da>1024+VAULT_DA && da <2048-VAULT_DA ))
|
|
return(0);
|
|
|
|
if (da>512&& da<2048-512)
|
|
{
|
|
angle += 1024;
|
|
angle &= 2047;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Along the middle of the fence?
|
|
//
|
|
|
|
wx = p_person->WorldPos.X >> 8;
|
|
wy = p_person->WorldPos.Y >> 8;
|
|
wz = p_person->WorldPos.Z >> 8;
|
|
|
|
signed_dist_to_line_with_normal(
|
|
p_facet->x[0] << 8, p_facet->z[0] << 8,
|
|
p_facet->x[1] << 8, p_facet->z[1] << 8,
|
|
wx, wz,
|
|
&dist,
|
|
&norm_x,
|
|
&norm_z,
|
|
&on);
|
|
|
|
if(!on)
|
|
return(0);
|
|
|
|
//
|
|
// Make sure you are looking at the fence rather than away from it.
|
|
//
|
|
|
|
SLONG ldx = -SIN(angle) >> 8;
|
|
SLONG ldz = -COS(angle) >> 8;
|
|
|
|
if (!two4_line_intersection(
|
|
p_facet->x[0] << 8, p_facet->z[0] << 8,
|
|
p_facet->x[1] << 8, p_facet->z[1] << 8,
|
|
wx, wz,
|
|
wx + ldx, wz + ldz))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// If the other side of the fence is a no-go square...
|
|
//
|
|
|
|
if (PAP_2HI(wx + ldx >> 8, wz + ldz >> 8).Flags & PAP_FLAG_NOGO)
|
|
{
|
|
p_person->Velocity=0;
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Make sure we're not going to vault into a building.
|
|
//
|
|
|
|
{
|
|
SLONG flx = wx + ldx + (-ldz >> 3) >> 8;
|
|
SLONG fly = wz + ldz + (+ldx >> 3) >> 8;
|
|
|
|
SLONG frx = wx + ldx - (-ldz >> 3) >> 8;
|
|
SLONG fry = wz + ldz - (+ldx >> 3) >> 8;
|
|
|
|
SLONG fl_height = MAVHEIGHT(flx,fly) << 6;
|
|
SLONG fr_height = MAVHEIGHT(frx,fry) << 6;
|
|
|
|
if (fl_height - (p_person->WorldPos.Y >> 8) > 0x50 ||
|
|
fr_height - (p_person->WorldPos.Y >> 8) > 0x50)
|
|
{
|
|
//
|
|
// Vaulting into a wall!
|
|
//
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set angle for fence.
|
|
//
|
|
|
|
p_person->Draw.Tweened->Angle = angle;
|
|
|
|
//
|
|
// Set position for fence.
|
|
//
|
|
|
|
{
|
|
SLONG len;
|
|
SLONG adx,adz;
|
|
SLONG odx,odz;
|
|
if(dist<0)
|
|
{
|
|
norm_x=-norm_x;
|
|
norm_z=-norm_z;
|
|
}
|
|
dist=abs(dist);
|
|
|
|
adx=abs(norm_x);
|
|
adz=abs(norm_z);
|
|
|
|
len=QDIST2(adx,adz);
|
|
if(len==0)
|
|
len=1;
|
|
|
|
mdx=((norm_x*(req_dist-dist))<<8)/len;
|
|
mdz=((norm_z*(req_dist-dist))<<8)/len;
|
|
|
|
|
|
new_position.X=p_person->WorldPos.X+(mdx);
|
|
new_position.Z=p_person->WorldPos.Z+(mdz);
|
|
|
|
new_position.Y=p_person->WorldPos.Y;
|
|
move_thing_on_map(p_person,&new_position);
|
|
}
|
|
|
|
|
|
|
|
return(1);
|
|
}
|
|
|
|
SLONG set_person_pos_for_fence(Thing *p_person,SLONG col,SLONG set_pos,SLONG req_dist)
|
|
{
|
|
SLONG mdx,mdz,dx,dz,len,dist;
|
|
SLONG near_x,near_z;
|
|
SLONG wx,wy,wz;
|
|
SLONG angle;
|
|
GameCoord new_position;
|
|
SLONG on,norm_x,norm_z;
|
|
struct DFacet *p_facet;
|
|
|
|
p_facet=&dfacets[col];
|
|
|
|
dx = p_facet->x[1] - p_facet->x[0] << 8;
|
|
dz = p_facet->z[1] - p_facet->z[0] << 8;
|
|
|
|
mdx=abs(dx);
|
|
mdz=abs(dz);
|
|
|
|
{
|
|
angle=Arctan(-mdx,mdz)+1024+512;
|
|
if(angle<0)
|
|
angle=2048+angle;
|
|
angle=angle&2047;
|
|
|
|
//
|
|
// The angle is never out of range anymore.
|
|
//
|
|
SLONG da = angle - p_person->Draw.Tweened->Angle;
|
|
|
|
//
|
|
// and now it is out of range again
|
|
//
|
|
|
|
if ((abs(da)>112&& abs(da)<1024-112) || (abs(da)>1024+112 && abs(da)<2048-112))
|
|
return(1);
|
|
|
|
|
|
|
|
if (abs(da)>512&&abs(da)<2048-512)
|
|
{
|
|
angle += 1024;
|
|
angle &= 2047;
|
|
}
|
|
|
|
|
|
MSG_add(" SET LAND ON FENCE angle %d person angle %d \n",angle,p_person->Draw.Tweened->Angle);
|
|
|
|
}
|
|
|
|
//
|
|
// Check to see if there is a nogo zone in front of the person.
|
|
// If so, then she shouldn't grab.
|
|
//
|
|
|
|
{
|
|
SLONG dax = -SIN(angle);
|
|
SLONG daz = -COS(angle);
|
|
|
|
SLONG mx = p_person->WorldPos.X + dax >> 16;
|
|
SLONG mz = p_person->WorldPos.Z + daz >> 16;
|
|
|
|
if (!WITHIN(mx, 0, PAP_SIZE_HI - 1) ||
|
|
!WITHIN(mz, 0, PAP_SIZE_HI - 1))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (PAP_2HI(mx,mz).Flags & PAP_FLAG_NOGO)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// set the angle we want them at before we find out the arse position
|
|
//
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,0,&wx,&wy,&wz);
|
|
|
|
wx += p_person->WorldPos.X >> 8;
|
|
wy += p_person->WorldPos.Y >> 8;
|
|
wz += p_person->WorldPos.Z >> 8;
|
|
|
|
//
|
|
// check if person can actually grab the fence (i.e their hands are in range
|
|
//
|
|
|
|
{
|
|
SLONG fence_top = get_fence_top (wx,wz, col);
|
|
SLONG fence_bottom = get_fence_bottom(wx,wz, col);
|
|
|
|
if (WITHIN(wy, fence_bottom + 64, fence_top - 64))
|
|
{
|
|
//
|
|
// Okay to grab.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Wrong y-position to grab fence.
|
|
//
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Along the middle of the fence?
|
|
//
|
|
|
|
signed_dist_to_line_with_normal(
|
|
p_facet->x[0] << 8, p_facet->z[0] << 8,
|
|
p_facet->x[1] << 8, p_facet->z[1] << 8,
|
|
wx, wz,
|
|
&dist,
|
|
&norm_x,
|
|
&norm_z,
|
|
&on);
|
|
|
|
if(!on)
|
|
return(1);
|
|
|
|
//
|
|
// Set position for fence.
|
|
//
|
|
p_person->Draw.Tweened->Angle=angle;
|
|
|
|
{
|
|
SLONG len;
|
|
SLONG adx,adz;
|
|
if(dist<0)
|
|
{
|
|
norm_x=-norm_x;
|
|
norm_z=-norm_z;
|
|
}
|
|
dist=abs(dist);
|
|
|
|
adx=abs(norm_x);
|
|
adz=abs(norm_z);
|
|
|
|
len=QDIST2(adx,adz);
|
|
if(len==0)
|
|
len=1;
|
|
|
|
mdx=((norm_x*(req_dist-dist))<<8)/len;
|
|
mdz=((norm_z*(req_dist-dist))<<8)/len;
|
|
|
|
new_position.X=p_person->WorldPos.X+(mdx);
|
|
new_position.Z=p_person->WorldPos.Z+(mdz);
|
|
|
|
new_position.Y=p_person->WorldPos.Y;
|
|
move_thing_on_map(p_person,&new_position);
|
|
}
|
|
|
|
|
|
return(0);
|
|
}
|
|
|
|
SLONG set_person_pos_for_half_step(Thing *p_person,SLONG col)
|
|
{
|
|
SLONG dx,dz;
|
|
SLONG wall_angle;
|
|
struct DFacet *p_facet;
|
|
p_facet=&dfacets[col];
|
|
SLONG on,norm_x,norm_z;
|
|
|
|
SLONG wx,wy,wz;
|
|
|
|
|
|
if(am_i_facing_wall(p_person,col,&wall_angle))
|
|
{
|
|
SLONG dist,angle,wy;
|
|
SLONG mx,my,mz;
|
|
|
|
wx=p_person->WorldPos.X>>8;
|
|
wy=p_person->WorldPos.Y>>8;
|
|
wz=p_person->WorldPos.Z>>8;
|
|
|
|
dx = -(SIN(wall_angle)) >> 9;
|
|
dz = -(COS(wall_angle)) >> 9;
|
|
|
|
mx=(wx+dx)>>8;
|
|
mz=(wz+dz)>>8;
|
|
|
|
if (p_person->Genus.Person->Ware)
|
|
{
|
|
//
|
|
// Would this take Darci out of her warehouse?
|
|
//
|
|
|
|
if (!WARE_in_floorplan(p_person->Genus.Person->Ware, mx, mz))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
my = WARE_calc_height_at(p_person->Genus.Person->Ware, (mx << 8) + 0x80, (mz << 8) + 0x80);
|
|
}
|
|
else
|
|
{
|
|
my = MAVHEIGHT(mx,mz) << 6;
|
|
|
|
}
|
|
|
|
if(wy<my-196 || wy>my-64)
|
|
return(0);
|
|
|
|
|
|
signed_dist_to_line_with_normal(
|
|
p_facet->x[0] << 8, p_facet->z[0] << 8,
|
|
p_facet->x[1] << 8, p_facet->z[1] << 8,
|
|
wx, wz,
|
|
&dist,
|
|
&norm_x,
|
|
&norm_z,
|
|
&on);
|
|
|
|
if(!on)
|
|
return(0);
|
|
|
|
{
|
|
SLONG ax1;
|
|
SLONG az1;
|
|
SLONG ax2;
|
|
SLONG az2;
|
|
|
|
if (p_facet->x[0] == p_facet->x[1])
|
|
{
|
|
ax1 = p_facet->x[0] << 8;
|
|
ax2 = p_facet->x[0] << 8;
|
|
|
|
az1 = wz & ~0xff;
|
|
az2 = az1 + 256;
|
|
}
|
|
else
|
|
{
|
|
ax1 = wx & ~0xff;
|
|
ax2 = ax1 + 256;
|
|
|
|
az1 = p_facet->z[0] << 8;
|
|
az2 = p_facet->z[0] << 8;
|
|
|
|
}
|
|
|
|
//
|
|
// If there is a fence lying along this facet- then we
|
|
// can't step up 'through' the fence.
|
|
//
|
|
|
|
if (does_fence_lie_along_line(
|
|
ax1, az1,
|
|
ax2, az2))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if(abs(dist)<60)
|
|
{
|
|
dist=abs(dist);
|
|
p_person->Draw.Tweened->Angle=wall_angle;
|
|
angle=(p_person->Draw.Tweened->Angle)&2047;
|
|
|
|
dx = (SIN(angle) * (40-dist)) >> 8;
|
|
dz = (COS(angle) * (40-dist)) >> 8;
|
|
person_normal_move_dxdz(p_person,dx,dz);
|
|
// move_thing_on_map_dxdydz(p_person,dx,0,dz);
|
|
return(1);
|
|
}
|
|
}
|
|
return(0);
|
|
|
|
}
|
|
|
|
inline SLONG is_facet_vaultable(SLONG facet)
|
|
{
|
|
struct DFacet *p_facet;
|
|
|
|
p_facet=&dfacets[facet];
|
|
if(p_facet->FacetType==STOREY_TYPE_FENCE ||p_facet->FacetType==STOREY_TYPE_FENCE_FLAT)
|
|
// if((p_facet->FacetFlags & FACET_FLAG_ONBUILDING) ==0)
|
|
if(p_facet->Height==2)
|
|
if(p_facet->BlockHeight==16)
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
inline SLONG is_facet_half_step(SLONG facet)
|
|
{
|
|
struct DFacet *p_facet;
|
|
|
|
p_facet=&dfacets[facet];
|
|
|
|
if(p_facet->FacetType==STOREY_TYPE_NORMAL)
|
|
if((p_facet->Height * p_facet->BlockHeight << 2)==128)
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
SLONG set_person_land_on_fence(Thing *p_person,SLONG col,SLONG set_pos,SLONG while_walking)
|
|
{
|
|
SLONG ret;
|
|
SLONG dist=45;
|
|
|
|
SLONG wall_angle;
|
|
|
|
if(!am_i_facing_wall(p_person,col,&wall_angle,256))
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
dist=60;
|
|
|
|
MSG_add(" set person land on fence");
|
|
|
|
if(while_walking==0)
|
|
if (is_facet_vaultable(col))
|
|
{
|
|
// return;
|
|
|
|
if (set_person_vault(p_person, col))
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Leave fight mode when you grab something.
|
|
//
|
|
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
|
|
if(ret=set_person_pos_for_fence(p_person,col,set_pos,dist))
|
|
{
|
|
switch(ret)
|
|
{
|
|
case 1:
|
|
//
|
|
// hands above it
|
|
//
|
|
|
|
// if(p_person->SubState == SUB_STATE_DROP_DOWN ||p_person->SubState == SUB_STATE_DROP_DOWN_OFF_FACE)
|
|
return(0);
|
|
if(while_walking==0)
|
|
set_person_drop_down(p_person,PERSON_DROP_DOWN_KEEP_VEL|PERSON_DROP_DOWN_KEEP_DY);
|
|
p_person->Velocity=1;
|
|
break;
|
|
|
|
}
|
|
return(1);
|
|
}
|
|
set_generic_person_state_function(p_person,STATE_CLIMBING);
|
|
p_person->SubState=SUB_STATE_CLIMB_LANDING;
|
|
queue_anim(p_person,ANIM_LAND_ON_FENCE);
|
|
/*
|
|
p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_LAND_ON_FENCE];
|
|
p_person->Draw.Tweened->CurrentAnim = ANIM_LAND_ON_FENCE;
|
|
*/
|
|
p_person->Genus.Person->Action=ACTION_CLIMBING;
|
|
p_person->Draw.Tweened->Locked=0;
|
|
p_person->Velocity=0;
|
|
p_person->DeltaVelocity=-2;
|
|
p_person->DY=0;
|
|
p_person->Genus.Person->OnFacet=col; //_vects[col].Face; //wall
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C;
|
|
return(1);
|
|
|
|
}
|
|
|
|
SLONG set_person_kick_off_wall(Thing *p_person,SLONG col,SLONG set_pos)
|
|
{
|
|
SLONG dist=100;
|
|
MSG_add(" set person land on fence");
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
dist=110;
|
|
|
|
if(set_person_pos_for_fence(p_person,col,set_pos,dist)==-1)
|
|
return(0);
|
|
set_generic_person_state_function(p_person,STATE_FIGHTING);
|
|
p_person->SubState=SUB_STATE_WALL_KICK;
|
|
queue_anim(p_person,ANIM_WALL_KICK);
|
|
|
|
p_person->Genus.Person->Action=ACTION_FIGHT_KICK;
|
|
p_person->Draw.Tweened->Locked=0;
|
|
p_person->Velocity=0;
|
|
p_person->DeltaVelocity=0;
|
|
p_person->DY=0;
|
|
// p_person->OnFace=-col_vects[col].Face; //wall
|
|
// p_person->Genus.Person->Flags|=FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C;
|
|
return(1);
|
|
|
|
}
|
|
|
|
SLONG fight_any_gang_attacker(Thing *p_person)
|
|
{
|
|
if(p_person->SubState!=SUB_STATE_IDLE_CROUTCH_ARREST)
|
|
if(p_person->Genus.Person->GangAttack)
|
|
{
|
|
UWORD attacker;
|
|
if(attacker=get_any_gang_member(p_person))
|
|
{
|
|
// you are under attack by someone
|
|
ASSERT(TO_THING(attacker)->Class==CLASS_PERSON);
|
|
ASSERT(TO_THING(attacker)->State!=STATE_DEAD);
|
|
p_person->Genus.Person->Target=attacker;
|
|
if(p_person->Genus.Person->Mode!=PERSON_MODE_FIGHT)
|
|
{
|
|
person_enter_fight_mode(p_person);
|
|
set_anim(p_person,ANIM_FIGHT_READY);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
UWORD find_arrestee(Thing *p_person)
|
|
{
|
|
SLONG i;
|
|
SLONG dist;
|
|
SLONG score;
|
|
SLONG best_score;
|
|
SLONG best_answer;
|
|
|
|
best_score = 0;
|
|
best_answer = NULL;
|
|
|
|
extern THING_INDEX col_with[];
|
|
|
|
SLONG col_with_upto = THING_find_sphere(
|
|
p_person->WorldPos.X>>8,
|
|
p_person->WorldPos.Y>>8,
|
|
p_person->WorldPos.Z>>8,
|
|
0x280,
|
|
col_with,
|
|
MAX_COL_WITH,
|
|
1 << CLASS_PERSON);
|
|
|
|
for (i = 0; i < col_with_upto; i++)
|
|
{
|
|
Thing *p_found = TO_THING(col_with[i]);
|
|
|
|
if (p_found->Genus.Person->Flags2 & FLAG2_PERSON_INVULNERABLE)
|
|
{
|
|
//
|
|
// You can't arrest invulnerable people.
|
|
//
|
|
|
|
if (p_found->Genus.Person->pcom_ai != PCOM_AI_FIGHT_TEST)
|
|
{
|
|
//
|
|
// But you can arrest FIGHT_TEST DUMMIES!
|
|
//
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
dist = dist_to_target_pelvis(p_person, p_found);
|
|
score = 0;
|
|
|
|
if (dist < 128)
|
|
{
|
|
if (is_person_ko_and_lay_down(p_found))
|
|
{
|
|
score = 500 - dist;
|
|
|
|
if (p_found->Genus.Person->PersonType == PERSON_MIB1 ||
|
|
p_found->Genus.Person->PersonType == PERSON_MIB2 ||
|
|
p_found->Genus.Person->PersonType == PERSON_MIB3 )
|
|
{
|
|
score=0;
|
|
}
|
|
|
|
if (p_found->Genus.Person->PersonType == PERSON_COP)
|
|
{
|
|
if (!(p_found->Genus.Person->Flags2 & FLAG2_PERSON_GUILTY))
|
|
{
|
|
//
|
|
// cant arrest cops!
|
|
//
|
|
score=0;
|
|
}
|
|
}
|
|
|
|
// if (p_found->Genus.Person->PersonType == PERSON_COP ||
|
|
if( p_found->Genus.Person->PersonType == PERSON_ROPER ||
|
|
p_found->Genus.Person->PersonType == PERSON_HOSTAGE)
|
|
{
|
|
score -= 250;
|
|
}
|
|
|
|
if (p_found->Genus.Person->pcom_ai == PCOM_AI_BODYGUARD && EWAY_get_person(p_found->Genus.Person->pcom_ai_other) == THING_NUMBER(p_person))
|
|
{
|
|
//
|
|
// Don't arrest your own bodyguards!
|
|
//
|
|
|
|
score = 0;
|
|
}
|
|
|
|
}
|
|
else
|
|
if (p_found->Genus.Person->pcom_ai == PCOM_AI_FIGHT_TEST)
|
|
{
|
|
if (p_found->State == STATE_DEAD && p_found->SubState == SUB_STATE_DEAD_INJURED)
|
|
{
|
|
score = 500 - dist;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (score > 0)
|
|
{
|
|
if (best_score < score)
|
|
{
|
|
best_score = score;
|
|
best_answer = col_with[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
return best_answer;
|
|
|
|
/*
|
|
|
|
UWORD s_index;
|
|
Thing *p_target;
|
|
extern SLONG THING_find_nearest_person(Thing *p_person,SLONG radius,ULONG classes);
|
|
s_index = THING_find_nearest_person(p_person,256,1<<CLASS_PERSON);
|
|
|
|
if(s_index)
|
|
{
|
|
p_target=TO_THING(s_index);
|
|
|
|
|
|
if(dist_to_target_pelvis(p_person,p_target)<128 && is_person_ko(p_target)) // 128 was 64
|
|
{
|
|
return(s_index);
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
|
|
*/
|
|
}
|
|
|
|
UWORD find_corpse(Thing *p_person)
|
|
{
|
|
UWORD s_index;
|
|
Thing *p_target;
|
|
extern SLONG THING_find_nearest_person(Thing *p_person,SLONG radius,ULONG classes);
|
|
s_index = THING_find_nearest_person(p_person,256,1<<CLASS_PERSON);
|
|
|
|
if(s_index)
|
|
{
|
|
p_target=TO_THING(s_index);
|
|
|
|
|
|
if(dist_to_target_pelvis(p_person,p_target)<128 && p_target->State == STATE_DEAD && p_target->SubState == SUB_STATE_DEAD_INJURED) // 128 was 64
|
|
{
|
|
return(s_index);
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
UWORD perform_arrest(Thing *p_person,UWORD s_index)
|
|
{
|
|
Thing *p_target;
|
|
|
|
p_target=TO_THING(s_index);
|
|
|
|
|
|
if(s_index)
|
|
{
|
|
SLONG ax,ay,az;
|
|
/*
|
|
calc_sub_objects_position(p_target,p_target->Draw.Tweened->AnimTween,SUB_OBJECT_PELVIS,&ax,&ay,&az);
|
|
ax+=p_person->WorldPos.X>>8;
|
|
ay+=p_person->WorldPos.Y>>8;
|
|
az+=p_person->WorldPos.Z>>8;
|
|
|
|
extern void add_damage_text(SWORD x,SWORD y,SWORD z,CBYTE *text);
|
|
add_damage_text(ax,ay,az,"Arrested");
|
|
*/
|
|
PANEL_new_info_message(XLAT_str(X_ARRESTED));
|
|
|
|
return(1);
|
|
}
|
|
return(0);
|
|
|
|
}
|
|
|
|
void lock_to_compass(Thing *p_thing);
|
|
|
|
void fn_person_search(Thing *p_person)
|
|
{
|
|
UWORD last_timer;
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_SEARCH_PRIM:
|
|
case SUB_STATE_SEARCH_CORPSE:
|
|
|
|
person_normal_animate(p_person);
|
|
|
|
if(!continue_pressing_action(p_person))
|
|
{
|
|
MFX_stop(THING_NUMBER(p_person),S_SEARCH_END);
|
|
|
|
if (p_person->SubState == SUB_STATE_SEARCH_CORPSE)
|
|
{
|
|
set_anim(p_person, ANIM_CROUTCH_GETUP);
|
|
p_person->SubState = SUB_STATE_SEARCH_GETUP;
|
|
}
|
|
else
|
|
{
|
|
set_person_idle(p_person);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
last_timer = p_person->Genus.Person->Timer1;
|
|
|
|
p_person->Genus.Person->Timer1+=400 * TICK_RATIO >> TICK_SHIFT;
|
|
|
|
if(p_person->Genus.Person->Timer1>=(125<<8)) // Stays at 100 for a while!
|
|
{
|
|
set_action_used(p_person);
|
|
set_person_idle(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
if (last_timer < (100 << 8) &&
|
|
p_person->Genus.Person->Timer1 >= (100 << 8))
|
|
{
|
|
release_searched_item(p_person);
|
|
|
|
|
|
if (p_person->SubState == SUB_STATE_SEARCH_CORPSE)
|
|
{
|
|
set_anim(p_person, ANIM_CROUTCH_GETUP);
|
|
p_person->SubState = SUB_STATE_SEARCH_GETUP;
|
|
p_person->Genus.Person->Target=0;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_SEARCH_GETUP:
|
|
|
|
{
|
|
SLONG end = person_normal_animate(p_person);
|
|
|
|
if (end)
|
|
{
|
|
set_action_used(p_person);
|
|
set_person_idle(p_person);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void set_person_random_idle(Thing *p_person)
|
|
{
|
|
SLONG anim=Random();
|
|
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
queue_anim(p_person,anim);
|
|
}
|
|
|
|
p_person->Genus.Person->Timer1=(Random()&0xff)+400;
|
|
|
|
switch(p_person->Genus.Person->PersonType)
|
|
{
|
|
case PERSON_ROPER:
|
|
queue_anim(p_person,anim&1?ANIM_BREATHE:ANIM_IDLE_SCRATCH1);
|
|
break;
|
|
|
|
case PERSON_COP:
|
|
{
|
|
switch(anim&3)
|
|
{
|
|
case 0:
|
|
anim=COP_ROPER_ANIM_IDLE1;
|
|
break;
|
|
case 1:
|
|
anim=COP_ROPER_ANIM_IDLE2;
|
|
break;
|
|
case 2:
|
|
anim=COP_ROPER_ANIM_IDLE3;
|
|
break;
|
|
case 3:
|
|
anim=COP_ROPER_ANIM_IDLE4;
|
|
break;
|
|
}
|
|
p_person->Draw.Tweened->QueuedFrame = game_chunk[ANIM_TYPE_ROPER].AnimList[anim];
|
|
p_person->Genus.Person->Flags2&=~FLAG2_SYNC_SOUNDFX;
|
|
p_person->Draw.Tweened->CurrentAnim = anim;
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
}
|
|
|
|
break;
|
|
/*
|
|
case PERSON_CIV:
|
|
switch(p_person->Draw.Tweened->MeshID)
|
|
{
|
|
case 7:
|
|
case 8:
|
|
//
|
|
// male idle's
|
|
//
|
|
set_anim_of_type(p_person,CIV_M_ANIM_STAND,ANIM_TYPE_CIV);
|
|
break;
|
|
case 9:
|
|
//
|
|
// female idle's
|
|
//
|
|
set_anim(p_person,ANIM_STAND_HIP);
|
|
|
|
break;
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
|
|
}
|
|
break;
|
|
*/
|
|
default:
|
|
switch(anim%3)
|
|
{
|
|
case 0:
|
|
anim=ANIM_IDLE_SCRATCH1;
|
|
break;
|
|
case 1:
|
|
anim=ANIM_IDLE_SCRATCH2;
|
|
break;
|
|
case 2:
|
|
anim=ANIM_BREATHE;
|
|
break;
|
|
}
|
|
|
|
queue_anim(p_person,anim);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void fn_person_idle(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
|
|
#ifndef NDEBUG
|
|
/*
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
AENG_world_line(
|
|
(p_person->WorldPos.X >> 8),
|
|
(p_person->WorldPos.Y >> 8) + 0x60,
|
|
(p_person->WorldPos.Z >> 8),
|
|
32,
|
|
0x00ffffff,
|
|
(p_person->WorldPos.X >> 8),
|
|
(p_person->WorldPos.Y >> 8) + 0x160,
|
|
(p_person->WorldPos.Z >> 8),
|
|
0,
|
|
0x00123456,
|
|
TRUE);
|
|
}
|
|
*/
|
|
#endif
|
|
|
|
/*
|
|
if(Keys[KB_7]&&ShiftFlag)
|
|
{
|
|
plant_feet(p_person);
|
|
|
|
}
|
|
if(Keys[KB_7]&&!ShiftFlag)
|
|
{
|
|
p_person->WorldPos.Y=0;
|
|
}
|
|
*/
|
|
|
|
if ((world_type==WORLD_TYPE_SNOW)&&!PersonIsMIB(p_person))
|
|
{
|
|
// breathe
|
|
if (MagicFrameCheck(p_person,5))
|
|
{
|
|
SLONG x,y,z;
|
|
calc_sub_objects_position(
|
|
p_person, p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_HEAD,
|
|
&x, &y, &z);
|
|
x<<=8; y<<=8; z<<=8;
|
|
x+=p_person->WorldPos.X;
|
|
y+=p_person->WorldPos.Y;
|
|
z+=p_person->WorldPos.Z;
|
|
PARTICLE_Add(x,y,z,256,10,256,POLY_PAGE_SMOKECLOUD2,
|
|
2+((Random()&3)<<2),0x7FFFFFFF,PFLAG_SPRITEANI|PFLAG_SPRITELOOP|PFLAG_FADE2|PFLAG_RESIZE,
|
|
30,30,1,10,1);
|
|
}
|
|
}
|
|
|
|
SlideSoundCheck(p_person);
|
|
|
|
if(p_person->Genus.Person->Mode==PERSON_MODE_FIGHT)
|
|
{
|
|
if(p_person->SubState!=SUB_STATE_IDLE_CROUTCH_ARREST)
|
|
{
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
if(p_person->Genus.Person->Target )
|
|
{
|
|
// ASSERT(TO_THING(p_person->Genus.Person->Target)->State!=STATE_DEAD);
|
|
|
|
}
|
|
else
|
|
{
|
|
//ASSERT(count_gang(p_person)==0);
|
|
}
|
|
|
|
}
|
|
if(p_person->Genus.Person->Target )
|
|
if(TO_THING(p_person->Genus.Person->Target)->State!=STATE_DEAD)
|
|
turn_to_face_thing(p_person,TO_THING(p_person->Genus.Person->Target),0);
|
|
|
|
//if(count_gang(p_person)==0)
|
|
{
|
|
Thing *p_attacker = is_person_under_attack_low_level(p_person, FALSE, 0x200);
|
|
|
|
if (p_attacker == NULL)
|
|
{
|
|
//
|
|
// nobody to fight, wait a while then exit fight mode
|
|
//
|
|
// if(p_person->Genus.Person->Agression++>100)
|
|
{
|
|
p_person->Genus.Person->Agression=0;
|
|
p_person->Genus.Person->Mode=PERSON_MODE_RUN;
|
|
p_person->Genus.Person->Target=0;
|
|
set_person_idle(p_person);
|
|
if(p_person->State==STATE_IDLE)
|
|
set_anim(p_person,ANIM_UNFIGHT);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p_person->Genus.Person->Target == NULL)
|
|
{
|
|
p_person->Genus.Person->Target = THING_NUMBER(p_attacker);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
else
|
|
{
|
|
//
|
|
// I'm fighting but I'm idle, my agression must be 0
|
|
//
|
|
// p_person->Genus.Person->Agression=0;
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if (p_person->OnFace>0)
|
|
{
|
|
ASSERT(WITHIN(p_person->OnFace, 1, next_prim_face4 - 1));
|
|
|
|
PrimFace4 *f4 = &prim_faces4[p_person->OnFace];
|
|
|
|
ASSERT(f4->FaceFlags & FACE_FLAG_WALKABLE);
|
|
|
|
//
|
|
// Take out the surfing for now...
|
|
//
|
|
|
|
#if WE_WANT_THE_SURFING_THAT_BREAKS_WHEN_YOU_PRESS_C
|
|
|
|
if (f4->FaceFlags & FACE_FLAG_WMOVE)
|
|
{
|
|
SLONG wmove_index;
|
|
|
|
WMOVE_Face *wf;
|
|
Thing *p_thing;
|
|
|
|
wmove_index=f4->ThingIndex;
|
|
|
|
wf = &WMOVE_face[wmove_index];
|
|
|
|
if(wf->thing)
|
|
{
|
|
p_thing = TO_THING(wf->thing);
|
|
if(p_thing->Class==CLASS_VEHICLE)
|
|
{
|
|
if(p_thing->Velocity>100)
|
|
{
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim!=ANIM_SURF_AK)
|
|
set_anim(p_person,ANIM_SURF_AK);
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim!=ANIM_SURF)
|
|
set_anim(p_person,ANIM_SURF);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim!=ANIM_STAND_READY)
|
|
set_anim(p_person,ANIM_STAND_READY);
|
|
|
|
}
|
|
}
|
|
person_normal_animate(p_person);
|
|
return;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
if (p_person->Genus.Person->PlayerID && p_person->Genus.Person->Mode != PERSON_MODE_FIGHT && !person_has_gun_out(p_person))
|
|
{
|
|
//
|
|
// You are a player and you're not in fight mode.
|
|
//
|
|
|
|
if (p_person->SubState!=SUB_STATE_IDLE_CROUTCH_ARREST)
|
|
{
|
|
Thing *p_attacker = is_person_under_attack_low_level(p_person, FALSE, 0x100);
|
|
|
|
|
|
if(p_person->Genus.Person->pcom_colour)
|
|
{
|
|
p_person->Genus.Person->pcom_colour--;
|
|
|
|
|
|
}
|
|
else
|
|
if (p_attacker)
|
|
{
|
|
SLONG anim;
|
|
|
|
//
|
|
// You are under attack by someone.
|
|
//
|
|
|
|
ASSERT(p_attacker->Class==CLASS_PERSON);
|
|
|
|
p_person->Genus.Person->Target = THING_NUMBER(p_attacker);
|
|
person_enter_fight_mode(p_person); //for fuck's sake get in fight mode
|
|
anim = find_idle_fight_stance(p_person);
|
|
set_anim(p_person,anim);
|
|
}
|
|
}
|
|
|
|
/*
|
|
if(p_person->Genus.Person->GangAttack)
|
|
{
|
|
UWORD attacker;
|
|
if(attacker=get_any_gang_member(p_person))
|
|
{
|
|
SLONG anim;
|
|
// you are under attack by someone
|
|
ASSERT(TO_THING(attacker)->Class==CLASS_PERSON);
|
|
p_person->Genus.Person->Target=attacker; //get_any_gang_member(p_person);
|
|
person_enter_fight_mode(p_person); //for fuck's sake get in fight mode
|
|
|
|
anim=find_idle_fight_stance(p_person);
|
|
set_anim(p_person,anim);
|
|
// CONSOLE_text("doing change 2",1000);
|
|
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case 0:
|
|
//
|
|
// check to see if you should slip down the slope your idle on
|
|
//
|
|
{
|
|
SLONG slope,angle;
|
|
if(p_person->Genus.Person->InsideIndex)
|
|
{
|
|
slope=0;
|
|
}
|
|
else
|
|
{
|
|
|
|
if(p_person->OnFace<0)
|
|
{
|
|
slope=RFACE_on_slope(-p_person->OnFace,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle);
|
|
}
|
|
else
|
|
{
|
|
|
|
slope=PAP_on_slope(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,&angle)>>1;
|
|
}
|
|
|
|
if(slope>50)
|
|
{
|
|
set_anim(p_person,ANIM_FALLING);
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState=SUB_STATE_SLIPPING;
|
|
p_person->Draw.Tweened->AngleTo=angle;
|
|
slope=MIN(slope-50,10);
|
|
slope=MAX(slope,50);
|
|
change_velocity_to(p_person,slope);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// if(p_thing->Genus.Person->AnimType!=2)
|
|
|
|
|
|
if(p_person->Draw.Tweened->DRoll && p_person->Draw.Tweened->FrameIndex==2) //&& (p_person->Genus.Person->AnimType!=2))
|
|
{
|
|
end=0;
|
|
}
|
|
else
|
|
{
|
|
end = person_normal_animate(p_person);
|
|
/*
|
|
if(p_person->Genus.Person->PlayerID)
|
|
if(p_person->Genus.Person->Flags2&FLAG2_PERSON_LOOK)
|
|
lock_to_compass(p_person);
|
|
*/
|
|
|
|
}
|
|
p_person->Draw.Tweened->DRoll=0;
|
|
|
|
if(end&&(p_person->Draw.Tweened->CurrentAnim!=ANIM_IDLE_SCRATCH1))
|
|
{
|
|
p_person->Draw.Tweened->CurrentAnim = ANIM_STAND_READY;
|
|
|
|
}
|
|
|
|
//
|
|
// Is this person holding a baseball bat?
|
|
//
|
|
/*
|
|
if (p_person->Genus.Person->SpecialUse &&
|
|
TO_THING(p_person->Genus.Person->SpecialUse)->Genus.Special->SpecialType == SPECIAL_BASEBALLBAT)
|
|
{
|
|
}
|
|
else
|
|
if (p_person->Draw.Tweened->CurrentAnim==ANIM_FIGHT)
|
|
{
|
|
}
|
|
else
|
|
*/
|
|
if (p_person->Genus.Person->Mode == PERSON_MODE_FIGHT)
|
|
{
|
|
if (end == 1)
|
|
{
|
|
SLONG anim;
|
|
anim=find_idle_fight_stance(p_person);
|
|
|
|
queue_anim(p_person, anim);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Genus.Person->SpecialUse)
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
#ifndef PSX
|
|
if(p_person->Genus.Person->Timer1--==0)
|
|
{
|
|
set_person_random_idle(p_person);
|
|
/*
|
|
SWORD the_anim=ANIM_IDLE_SCRATCH1+(p_person->Genus.Person->Timer1&1);
|
|
p_person->Genus.Person->Timer1=(Random()&0xff)+400;
|
|
|
|
|
|
if (p_person->Genus.Person->PersonType==PERSON_ROPER) // naff hack
|
|
the_anim=ANIM_IDLE_SCRATCH1;
|
|
|
|
// p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][the_anim]; //teeter
|
|
queue_anim(p_person,the_anim);
|
|
*/
|
|
}
|
|
|
|
// "It says here that 'Drinky Winky' of the teletubbies is obviously
|
|
// an abusive drunk because of the bottle of booze he carries..."
|
|
// "THAT'S NOT A BOTTLE OF BOOZE! It's his magic bottle that makes
|
|
// his problems go away! ... ... ... ... um ... ... nevermind."
|
|
if ((p_person->Genus.Person->PersonType==PERSON_ROPER)&&(p_person->Draw.Tweened->CurrentAnim==ANIM_IDLE_SCRATCH1)) {
|
|
if (p_person->Draw.Tweened->FrameIndex>=3) {
|
|
if (p_person->Draw.Tweened->FrameIndex>=17)
|
|
// p_person->Draw.Tweened->PersonID = 0; // back to normal hand
|
|
p_person->Draw.Tweened->PersonID&= ~0xe0;
|
|
else
|
|
{
|
|
p_person->Draw.Tweened->PersonID&= ~0xe0;
|
|
p_person->Draw.Tweened->PersonID|= 7<<5; // roper's magic bottle
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
|
|
if(Keys[KB_0])
|
|
{
|
|
p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][61]; //teeter
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
|
if(0 && end==1)
|
|
{
|
|
switch (p_person->Genus.Person->AnimType)
|
|
{// darci
|
|
// case ANIM_TYPE_ROPER:
|
|
// set_locked_anim(p_person,ANIM_BREATHE,SUB_OBJECT_LEFT_FOOT);
|
|
// break;
|
|
default:
|
|
// p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_BREATHE];
|
|
break;
|
|
|
|
}
|
|
//p_person->Draw.Tweened->PersonID = 0;
|
|
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_IDLE_CROUTCH:
|
|
end = person_normal_animate(p_person);
|
|
|
|
if(end==1)
|
|
{
|
|
p_person->SubState=SUB_STATE_IDLE_CROUTCHING;
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
/*
|
|
if(perform_arrest(p_person))
|
|
{
|
|
set_person_idle(p_person);
|
|
}
|
|
*/
|
|
}
|
|
break;
|
|
case SUB_STATE_IDLE_CROUTCH_ARREST:
|
|
end = person_normal_animate(p_person);
|
|
|
|
if(end==1)
|
|
{
|
|
//p_person->SubState=SUB_STATE_IDLE_CROUTCHING;
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_NON_INT_M; //|FLAG_PERSON_NON_INT_C;
|
|
perform_arrest(p_person,p_person->Genus.Person->Target);
|
|
|
|
|
|
|
|
set_person_idle(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_IDLE_CROUTCHING:
|
|
break;
|
|
|
|
case SUB_STATE_IDLE_UNCROUCH:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
{
|
|
if(p_person->Draw.Tweened->FrameIndex>1)
|
|
end=1;
|
|
}
|
|
|
|
if (end)
|
|
{
|
|
set_person_idle(p_person);
|
|
|
|
/*
|
|
SLONG anim;
|
|
p_person->SubState=0;
|
|
|
|
if (person_has_gun_out(p_person))
|
|
{
|
|
set_person_aim(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
p_person->Genus.Person->Timer1=(Random()&0xff)+100;
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
p_person->Genus.Person->Action=ACTION_IDLE;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
p_person->Velocity=0;
|
|
|
|
if (p_person->Genus.Person->Mode == PERSON_MODE_FIGHT)
|
|
{
|
|
anim = ANIM_FIGHT;
|
|
}
|
|
else
|
|
{
|
|
anim = ANIM_STAND_READY;
|
|
}
|
|
|
|
set_anim(p_person,anim);
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,anim);
|
|
set_person_sidle(p_person);
|
|
*/
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void PCOM_set_person_ai_flee_person(Thing *p_person,Thing *p_scary);
|
|
void PCOM_make_driver_run_away(Thing *p_driver, Thing *p_scary);
|
|
|
|
void set_person_in_vehicle(Thing *p_person,Thing *p_car)
|
|
{
|
|
SLONG sample;
|
|
|
|
if(p_car->Genus.Vehicle->Driver)
|
|
{
|
|
Thing *other_driver;
|
|
|
|
// ASSERT(0); // lets check it works
|
|
//
|
|
// this car has a driver allready, we must have both got in at the same time!
|
|
//
|
|
|
|
other_driver=TO_THING(p_car->Genus.Vehicle->Driver);
|
|
|
|
if(other_driver->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// theres a player in the car, let them drive, we will simply run away
|
|
//
|
|
p_person->Genus.Person->InCar = 0;
|
|
PCOM_set_person_ai_flee_person(p_person, other_driver);
|
|
}
|
|
else
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// player getting in a car that allready has a driver
|
|
//
|
|
p_car->Velocity=0; //make sure car is stopped dead so driver can get out
|
|
|
|
PCOM_make_driver_run_away(other_driver, p_person); // make current driver run away
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
ASSERT(p_car->Class==CLASS_VEHICLE);
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_DRIVING;
|
|
p_person->Genus.Person->InCar = THING_NUMBER(p_car);
|
|
p_person->SubState = SUB_STATE_INSIDE_VEHICLE;
|
|
remove_thing_from_map(p_person);
|
|
p_car->Genus.Vehicle->Flags|=FLAG_FURN_DRIVING;
|
|
p_car->Genus.Vehicle->Flags&=~FLAG_VEH_ANIMATING;
|
|
p_car->Genus.Vehicle->Driver=THING_NUMBER(p_person);
|
|
set_state_function(p_car, STATE_FDRIVING);
|
|
|
|
switch(p_car->Genus.Vehicle->Type)
|
|
{
|
|
case VEH_TYPE_AMBULANCE:
|
|
case VEH_TYPE_VAN:
|
|
case VEH_TYPE_JEEP:
|
|
case VEH_TYPE_MEATWAGON:
|
|
case VEH_TYPE_WILDCATVAN:
|
|
sample=S_VAN_START;
|
|
break;
|
|
|
|
case VEH_TYPE_CAR:
|
|
case VEH_TYPE_TAXI:
|
|
case VEH_TYPE_POLICE:
|
|
case VEH_TYPE_SEDAN:
|
|
sample=S_CAR_START;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
// p_car->Genus.Vehicle->SoundFX=play_quick_wave_xyz(p_car->WorldPos.X,p_car->WorldPos.Y,p_car->WorldPos.Z,sample,p_car->Genus.Vehicle->SoundFX,0);
|
|
|
|
// only darci's vehicle makes sound...
|
|
// if (p_person==NET_PERSON(0))
|
|
// MFX_play_thing(THING_NUMBER(p_car),sample,MFX_REPLACE|MFX_MOVING,p_car);
|
|
switch(p_car->Genus.Vehicle->Type)
|
|
{
|
|
case VEH_TYPE_AMBULANCE:
|
|
case VEH_TYPE_VAN:
|
|
case VEH_TYPE_JEEP:
|
|
case VEH_TYPE_MEATWAGON:
|
|
case VEH_TYPE_WILDCATVAN:
|
|
sample=S_VAN_IDLE;
|
|
break;
|
|
|
|
case VEH_TYPE_CAR:
|
|
case VEH_TYPE_TAXI:
|
|
case VEH_TYPE_POLICE:
|
|
case VEH_TYPE_SEDAN:
|
|
sample=S_CAR_IDLE;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
// play_quick_wave_xyz(p_car->WorldPos.X,p_car->WorldPos.Y,p_car->WorldPos.Z,sample,p_car->Genus.Vehicle->SoundFX,WAVE_PLAY_QUEUE|WAVE_LOOP);
|
|
|
|
//add this back in when queueing's done.
|
|
// if (p_person==NET_PERSON(0))
|
|
// MFX_play_thing(THING_NUMBER(p_car),sample,MFX_QUEUED|MFX_LOOPED|MFX_MOVING,p_car);
|
|
|
|
// set_vehicle_anim(p_car,1);
|
|
}
|
|
|
|
void set_person_out_of_vehicle(Thing *p_person)
|
|
{
|
|
Thing *p_car;
|
|
|
|
ASSERT(p_person->Genus.Person->InCar);
|
|
|
|
p_car=TO_THING(p_person->Genus.Person->InCar);
|
|
|
|
ASSERT(p_car->Class==CLASS_VEHICLE);
|
|
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_DRIVING|FLAG_PERSON_PASSENGER);
|
|
p_person->Genus.Person->InCar = 0;
|
|
// add_thing_to_map(p_person);
|
|
set_person_locked_idle_ready(p_person);
|
|
plant_feet(p_person);
|
|
p_car->Genus.Vehicle->Flags&=~FLAG_FURN_DRIVING;
|
|
// set_vehicle_anim(p_car,1);
|
|
/*
|
|
MFX_stop(THING_NUMBER(p_car),S_CARX_START);
|
|
MFX_stop(THING_NUMBER(p_car),S_CARX_START+1);
|
|
MFX_play_thing(THING_NUMBER(p_car),S_CARX_END,MFX_MOVING|MFX_REPLACE,p_car);
|
|
MFX_play_thing(THING_NUMBER(p_car),S_NULL,MFX_QUEUED|MFX_SHORT_QUEUE,p_car);
|
|
p_car->Genus.Vehicle->Flags^=FLAG_VEH_FX_STATE;
|
|
*/
|
|
}
|
|
|
|
|
|
//
|
|
// Change from current anim status to a totally fresh one,
|
|
// keeping a limb in the same place
|
|
//
|
|
|
|
void locked_anim_change(Thing *p_person,UWORD locked_object,UWORD anim,SLONG dangle)
|
|
{
|
|
SLONG lock_x1,lock_y1,lock_z1;
|
|
SLONG lock_x2,lock_y2,lock_z2;
|
|
DrawTween *draw_info;
|
|
GameCoord temp_pos;
|
|
|
|
ASSERT(anim);
|
|
|
|
ASSERT(global_anim_array[p_person->Genus.Person->AnimType][anim]);
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,locked_object,&lock_x1,&lock_y1,&lock_z1);
|
|
|
|
draw_info = p_person->Draw.Tweened;
|
|
draw_info->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][anim];
|
|
draw_info->QueuedFrame = 0;
|
|
draw_info->NextFrame = draw_info->CurrentFrame->NextFrame;
|
|
draw_info->AnimTween = 0;
|
|
draw_info->CurrentAnim = anim;
|
|
draw_info->FrameIndex = 0;
|
|
|
|
draw_info->Angle+=dangle;
|
|
draw_info->Angle&=2047;
|
|
|
|
calc_sub_objects_position(p_person,0,locked_object,&lock_x2,&lock_y2,&lock_z2);
|
|
//
|
|
// difference in lock co-ord is ammount to move by to maintain same position for limb
|
|
//
|
|
|
|
temp_pos.X=((+lock_x1-lock_x2)<<8)+p_person->WorldPos.X;
|
|
temp_pos.Y=((+lock_y1-lock_y2)<<8)+p_person->WorldPos.Y;
|
|
temp_pos.Z=((+lock_z1-lock_z2)<<8)+p_person->WorldPos.Z;
|
|
|
|
//LogText(" old lock %d %d %d \n",lock_x1,lock_y1,lock_z1);
|
|
//LogText(" new lock %d %d %d \n",lock_x2,lock_y2,lock_z2);
|
|
|
|
//LogText(" locked anim change dx dy dz %d %d %d \n",lock_x1-lock_x2,lock_y1-lock_y2,lock_z1-lock_z2);
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
}
|
|
void locked_anim_change_of_type(Thing *p_person,UWORD locked_object,UWORD anim,SLONG type)
|
|
{
|
|
SLONG lock_x1,lock_y1,lock_z1;
|
|
SLONG lock_x2,lock_y2,lock_z2;
|
|
DrawTween *draw_info;
|
|
GameCoord temp_pos;
|
|
|
|
ASSERT(anim);
|
|
|
|
ASSERT(global_anim_array[type][anim]);
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,locked_object,&lock_x1,&lock_y1,&lock_z1);
|
|
|
|
draw_info = p_person->Draw.Tweened;
|
|
draw_info->CurrentFrame = game_chunk[type].AnimList[anim];//global_anim_array[type][anim];
|
|
draw_info->QueuedFrame = 0;
|
|
draw_info->NextFrame = draw_info->CurrentFrame->NextFrame;
|
|
draw_info->AnimTween = 0;
|
|
draw_info->CurrentAnim = anim;
|
|
|
|
calc_sub_objects_position(p_person,0,locked_object,&lock_x2,&lock_y2,&lock_z2);
|
|
//
|
|
// difference in lock co-ord is ammount to move by to maintain same position for limb
|
|
//
|
|
|
|
temp_pos.X=((+lock_x1-lock_x2)<<8)+p_person->WorldPos.X;
|
|
temp_pos.Y=((+lock_y1-lock_y2)<<8)+p_person->WorldPos.Y;
|
|
temp_pos.Z=((+lock_z1-lock_z2)<<8)+p_person->WorldPos.Z;
|
|
|
|
//LogText(" old lock %d %d %d \n",lock_x1,lock_y1,lock_z1);
|
|
//LogText(" new lock %d %d %d \n",lock_x2,lock_y2,lock_z2);
|
|
|
|
//LogText(" locked anim change dx dy dz %d %d %d \n",lock_x1-lock_x2,lock_y1-lock_y2,lock_z1-lock_z2);
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
}
|
|
|
|
void locked_anim_change_height_type(Thing *p_person,UWORD locked_object,UWORD anim,SLONG type)
|
|
{
|
|
SLONG lock_x1,lock_y1,lock_z1;
|
|
SLONG lock_x2,lock_y2,lock_z2;
|
|
DrawTween *draw_info;
|
|
GameCoord temp_pos;
|
|
|
|
// ASSERT(global_anim_array[type][anim]);
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,locked_object,&lock_x1,&lock_y1,&lock_z1);
|
|
|
|
draw_info = p_person->Draw.Tweened;
|
|
draw_info->CurrentFrame = game_chunk[type].AnimList[anim]; //global_anim_array[type][anim];
|
|
draw_info->QueuedFrame = 0;
|
|
draw_info->NextFrame = draw_info->CurrentFrame->NextFrame;
|
|
draw_info->AnimTween = 0;
|
|
draw_info->CurrentAnim = anim;
|
|
|
|
calc_sub_objects_position(p_person,0,locked_object,&lock_x2,&lock_y2,&lock_z2);
|
|
//
|
|
// difference in lock co-ord is ammount to move by to maintain same position for limb
|
|
//
|
|
|
|
temp_pos.X=p_person->WorldPos.X;
|
|
temp_pos.Y=((+lock_y1-lock_y2)<<8)+p_person->WorldPos.Y;
|
|
temp_pos.Z=p_person->WorldPos.Z;
|
|
|
|
//LogText(" old lock %d %d %d \n",lock_x1,lock_y1,lock_z1);
|
|
//LogText(" new lock %d %d %d \n",lock_x2,lock_y2,lock_z2);
|
|
|
|
//LogText(" locked anim change dx dy dz %d %d %d \n",lock_x1-lock_x2,lock_y1-lock_y2,lock_z1-lock_z2);
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
}
|
|
|
|
SLONG set_limb_to_y(Thing *p_person,SLONG obj,SLONG y)
|
|
{
|
|
SLONG x1,y1,z1;
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,obj,&x1,&y1,&z1);
|
|
y1+=(p_person->WorldPos.Y>>8);
|
|
|
|
y-=y1;
|
|
|
|
p_person->WorldPos.Y+=y<<8;
|
|
return(0);
|
|
}
|
|
|
|
|
|
void locked_next_anim_change(Thing *p_person,UWORD locked_object,GameKeyFrame *queued_frame)
|
|
{
|
|
SLONG lock_x1,lock_y1,lock_z1;
|
|
SLONG lock_x2,lock_y2,lock_z2;
|
|
DrawTween *draw_info;
|
|
GameCoord temp_pos;
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,locked_object,&lock_x1,&lock_y1,&lock_z1);
|
|
|
|
draw_info=p_person->Draw.Tweened;
|
|
draw_info->NextFrame = queued_frame;
|
|
// draw_info->AnimTween=0;
|
|
// draw_info->CurrentAnim = anim;
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,locked_object,&lock_x2,&lock_y2,&lock_z2);
|
|
//
|
|
// difference in lock co-ord is ammount to move by to maintain same position for limb
|
|
//
|
|
|
|
temp_pos.X=((+lock_x1-lock_x2)<<8)+p_person->WorldPos.X;
|
|
temp_pos.Y=((+lock_y1-lock_y2)<<8)+p_person->WorldPos.Y;
|
|
temp_pos.Z=((+lock_z1-lock_z2)<<8)+p_person->WorldPos.Z;
|
|
|
|
//LogText(" old lock %d %d %d \n",lock_x1,lock_y1,lock_z1);
|
|
//LogText(" new lock %d %d %d \n",lock_x2,lock_y2,lock_z2);
|
|
|
|
//LogText(" locked anim change dx dy dz %d %d %d \n",lock_x1-lock_x2,lock_y1-lock_y2,lock_z1-lock_z2);
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
}
|
|
|
|
void locked_anim_change_end_type(Thing *p_person,UWORD locked_object,UWORD anim,SLONG type)
|
|
{
|
|
SLONG lock_x1,lock_y1,lock_z1;
|
|
SLONG lock_x2,lock_y2,lock_z2;
|
|
DrawTween *draw_info;
|
|
GameCoord temp_pos;
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,locked_object,&lock_x1,&lock_y1,&lock_z1);
|
|
|
|
draw_info=p_person->Draw.Tweened;
|
|
draw_info->CurrentFrame = game_chunk[type].AnimList[anim];//global_anim_array[type][anim];
|
|
draw_info->QueuedFrame = 0;
|
|
draw_info->NextFrame = draw_info->CurrentFrame->NextFrame;
|
|
|
|
while(draw_info->NextFrame->NextFrame)
|
|
{
|
|
draw_info->CurrentFrame = draw_info->NextFrame;
|
|
draw_info->NextFrame = draw_info->NextFrame->NextFrame;
|
|
|
|
|
|
}
|
|
draw_info->AnimTween=255;
|
|
draw_info->CurrentAnim = anim;
|
|
|
|
calc_sub_objects_position(p_person,draw_info->AnimTween,locked_object,&lock_x2,&lock_y2,&lock_z2);
|
|
//
|
|
// difference in lock co-ord is ammount to move by to maintain same position for limb
|
|
//
|
|
|
|
temp_pos.X=((+lock_x1-lock_x2)<<8)+p_person->WorldPos.X;
|
|
temp_pos.Y=((+lock_y1-lock_y2)<<8)+p_person->WorldPos.Y;
|
|
temp_pos.Z=((+lock_z1-lock_z2)<<8)+p_person->WorldPos.Z;
|
|
|
|
//LogText(" old lock %d %d %d \n",lock_x1,lock_y1,lock_z1);
|
|
//LogText(" new lock %d %d %d \n",lock_x2,lock_y2,lock_z2);
|
|
|
|
//LogText(" locked anim change dx dy dz %d %d %d \n",lock_x1-lock_x2,lock_y1-lock_y2,lock_z1-lock_z2);
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
}
|
|
|
|
void locked_anim_change_end(Thing *p_person,UWORD locked_object,UWORD anim)
|
|
{
|
|
SLONG lock_x1,lock_y1,lock_z1;
|
|
SLONG lock_x2,lock_y2,lock_z2;
|
|
DrawTween *draw_info;
|
|
GameCoord temp_pos;
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,locked_object,&lock_x1,&lock_y1,&lock_z1);
|
|
|
|
draw_info=p_person->Draw.Tweened;
|
|
draw_info->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][anim];
|
|
draw_info->QueuedFrame = 0;
|
|
draw_info->NextFrame = draw_info->CurrentFrame->NextFrame;
|
|
|
|
while(draw_info->NextFrame->NextFrame)
|
|
{
|
|
draw_info->CurrentFrame = draw_info->NextFrame;
|
|
draw_info->NextFrame = draw_info->NextFrame->NextFrame;
|
|
|
|
|
|
}
|
|
draw_info->AnimTween=255;
|
|
draw_info->CurrentAnim = anim;
|
|
|
|
calc_sub_objects_position(p_person,draw_info->AnimTween,locked_object,&lock_x2,&lock_y2,&lock_z2);
|
|
//
|
|
// difference in lock co-ord is ammount to move by to maintain same position for limb
|
|
//
|
|
|
|
temp_pos.X=((+lock_x1-lock_x2)<<8)+p_person->WorldPos.X;
|
|
temp_pos.Y=((+lock_y1-lock_y2)<<8)+p_person->WorldPos.Y;
|
|
temp_pos.Z=((+lock_z1-lock_z2)<<8)+p_person->WorldPos.Z;
|
|
|
|
//LogText(" old lock %d %d %d \n",lock_x1,lock_y1,lock_z1);
|
|
//LogText(" new lock %d %d %d \n",lock_x2,lock_y2,lock_z2);
|
|
|
|
//LogText(" locked anim change dx dy dz %d %d %d \n",lock_x1-lock_x2,lock_y1-lock_y2,lock_z1-lock_z2);
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
}
|
|
|
|
SLONG steep_cable(SLONG facet)
|
|
{
|
|
struct DFacet *p_facet;
|
|
SLONG dx,dy,dz,len,m;
|
|
p_facet=&dfacets[facet];
|
|
|
|
dx = abs(p_facet->x[1] - p_facet->x[0] << 8);
|
|
dz = abs(p_facet->z[1] - p_facet->z[0] << 8);
|
|
|
|
len=QDIST2(dx,dz);
|
|
|
|
dy=p_facet->Y[1]-p_facet->Y[0];
|
|
|
|
if(len==0)
|
|
len=1;
|
|
|
|
m=(dy<<8)/len;
|
|
|
|
|
|
return(m);
|
|
}
|
|
|
|
void face_down_cable(Thing *p_person,SLONG facet)
|
|
{
|
|
struct DFacet *p_facet;
|
|
SLONG dx,dy,dz,len,m;
|
|
p_facet=&dfacets[facet];
|
|
|
|
dx = (p_facet->x[1] - p_facet->x[0] << 8);
|
|
dy = (p_facet->Y[1] - p_facet->Y[0]);
|
|
dz = (p_facet->z[1] - p_facet->z[0] << 8);
|
|
|
|
if(dy>0)
|
|
{
|
|
p_person->Draw.Tweened->Angle=calc_angle(dx,dz);
|
|
}
|
|
else
|
|
{
|
|
p_person->Draw.Tweened->Angle=calc_angle(-dx,-dz);
|
|
|
|
}
|
|
}
|
|
|
|
SLONG find_best_cable_angle(Thing *p_person,SLONG facet)
|
|
{
|
|
struct DFacet *p_facet;
|
|
SLONG dx,dy,dz,len,m;
|
|
SLONG dangle,cable_angle;
|
|
|
|
p_facet=&dfacets[facet];
|
|
|
|
dx = (p_facet->x[1] - p_facet->x[0]) << 8;
|
|
dz = (p_facet->z[1] - p_facet->z[0]) << 8;
|
|
|
|
cable_angle=calc_angle(dx,dz);
|
|
|
|
dangle=p_person->Draw.Tweened->Angle-cable_angle;
|
|
|
|
if(abs(dangle)>1024)
|
|
return((cable_angle+1024)&2047);
|
|
else
|
|
return(cable_angle);
|
|
|
|
|
|
}
|
|
|
|
//
|
|
// see if persons hands are near to grabbing a ledge
|
|
//
|
|
SLONG grab_ledge(Thing *p_person)
|
|
{
|
|
SLONG x,y,z;
|
|
SLONG grab_x,grab_y,grab_z,type;
|
|
SLONG grab_angle;
|
|
SLONG face;
|
|
|
|
SLONG ignore_building;
|
|
|
|
if(p_person->Genus.Person->InsideIndex)
|
|
return(0);
|
|
|
|
//
|
|
// While we're grabbing a ledge- try grabbing a balloon!
|
|
//
|
|
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
BALLOON_find_grab(THING_NUMBER(p_person));
|
|
#endif
|
|
//
|
|
// Dont grab a ledge whilst falling backwards...
|
|
//
|
|
/*
|
|
if (p_person->SubState == SUB_STATE_DROP_DOWN && p_person->Velocity < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
*/
|
|
if (p_person->Flags & FLAGS_IN_BUILDING)
|
|
{
|
|
ignore_building = INDOORS_DBUILDING;
|
|
}
|
|
else
|
|
{
|
|
ignore_building = 0;
|
|
}
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,SUB_OBJECT_LEFT_HAND,&x,&y,&z);
|
|
|
|
{
|
|
SLONG rx,ry,rz;
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,SUB_OBJECT_RIGHT_HAND,&rx,&ry,&rz);
|
|
|
|
x+=rx;
|
|
y+=ry;
|
|
z+=rz;
|
|
|
|
x>>=1;
|
|
y>>=1;
|
|
z>>=1;
|
|
|
|
}
|
|
x+=p_person->WorldPos.X>>8;
|
|
y+=p_person->WorldPos.Y>>8;
|
|
z+=p_person->WorldPos.Z>>8;
|
|
|
|
//
|
|
// We grab the sewer floor in the sewers.
|
|
//
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
if (p_person->Flags & FLAGS_IN_SEWERS)
|
|
{
|
|
face = find_grab_face_in_sewers(
|
|
x,y,z,
|
|
50,40,
|
|
p_person->Draw.Tweened->Angle,
|
|
&grab_x,
|
|
&grab_y,
|
|
&grab_z,
|
|
&grab_angle);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SLONG radius=80;
|
|
if(p_person->State==STATE_CLIMBING)
|
|
radius=100;
|
|
face = find_grab_face(
|
|
x,y,z,
|
|
radius,40,
|
|
p_person->Draw.Tweened->Angle,
|
|
&grab_x,
|
|
&grab_y,
|
|
&grab_z,
|
|
&grab_angle,
|
|
ignore_building,
|
|
FALSE,&type,
|
|
p_person);
|
|
}
|
|
|
|
|
|
if(face)
|
|
{
|
|
//
|
|
// Leave fight mode when you grab something.
|
|
//
|
|
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
|
|
SLONG new_x,new_y,new_z, old_substate;
|
|
GameCoord temp_pos;
|
|
DrawTween *draw_info;
|
|
|
|
if(type==2)
|
|
{
|
|
if(p_person->SubState!=SUB_STATE_RUNNING_JUMP_FLY && p_person->SubState!=SUB_STATE_DROP_DOWN)
|
|
return(0);
|
|
if(p_person->DY>0)
|
|
return(0);
|
|
|
|
//grab_ladder
|
|
/*
|
|
//
|
|
// move person so new hand position is at grab_x,grab_y,grab_z
|
|
//
|
|
|
|
calc_sub_objects_position(p_person,0,SUB_OBJECT_LEFT_HAND,&new_x,&new_y,&new_z);
|
|
|
|
new_x+=p_person->WorldPos.X>>8;
|
|
new_y+=p_person->WorldPos.Y>>8;
|
|
new_z+=p_person->WorldPos.Z>>8;
|
|
|
|
//LogText(" left hand pos for grab face after anim change %d %d %d \n",new_x,new_y,new_z);
|
|
|
|
//LogText(" found a ledge offset %d %d %d to it \n",grab_x-new_x,grab_y-new_y,grab_z-new_z);
|
|
|
|
*/
|
|
temp_pos.X=grab_x<<8;
|
|
temp_pos.Y=p_person->WorldPos.Y;
|
|
temp_pos.Z=grab_z<<8;
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
// grabbed a ladder
|
|
p_person->Genus.Person->OnFacet=face;
|
|
p_person->Draw.Tweened->Angle = grab_angle;
|
|
set_generic_person_state_function(p_person,STATE_CLIMB_LADDER);
|
|
|
|
set_person_on_ladder(p_person);
|
|
return(1);
|
|
|
|
}
|
|
|
|
draw_info=p_person->Draw.Tweened;
|
|
|
|
draw_info->AnimTween=0;
|
|
p_person->Genus.Person->Action = ACTION_GRABBING_LEDGE;
|
|
set_generic_person_state_function(p_person,STATE_DANGLING);
|
|
old_substate=p_person->SubState;
|
|
p_person->SubState=SUB_STATE_GRAB_TO_DANGLE;
|
|
// p_person->Draw.Tweened->Angle = grab_angle;
|
|
|
|
if(type==1)
|
|
{
|
|
SLONG grad;
|
|
//
|
|
// grabbed a cable
|
|
//
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_ON_CABLE;
|
|
set_anim(p_person,ANIM_DEATH_SLIDE);
|
|
|
|
MinorEffortSound(p_person);
|
|
|
|
grad=steep_cable(face);
|
|
if(abs(grad)>10)
|
|
{
|
|
p_person->SubState=SUB_STATE_DEATH_SLIDE;
|
|
p_person->Velocity=0;
|
|
grad>>=6;
|
|
if(grad>16)
|
|
grad=16;
|
|
if(grad<2)
|
|
grad=2;
|
|
|
|
p_person->DeltaVelocity=abs(grad);
|
|
face_down_cable(p_person,face);
|
|
p_person->Genus.Person->Action = ACTION_DEATH_SLIDE;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (old_substate) {
|
|
case SUB_STATE_STANDING_JUMP:
|
|
MinorEffortSound(p_person);
|
|
TRACE("minoreffort(stand jump grab) %d\n",p_person->Draw.Tweened->CurrentAnim);
|
|
break;
|
|
case SUB_STATE_RUNNING_JUMP:
|
|
MinorEffortSound(p_person);
|
|
TRACE("minoreffort(running jump grab) %d\n",p_person->Draw.Tweened->CurrentAnim);
|
|
break;
|
|
case SUB_STATE_DROP_DOWN:
|
|
// just in case...
|
|
StopScreamFallSound(p_person);
|
|
// ideally check speed...
|
|
if (p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
MFX_play_thing(THING_NUMBER(p_person),S_ROPER_HIT_END-1,0,p_person);
|
|
else
|
|
MinorEffortSound(p_person);
|
|
TRACE("minoreffort(falling grab) %d\n",p_person->Draw.Tweened->CurrentAnim);
|
|
break;
|
|
case SUB_STATE_RUNNING_JUMP_FLY:
|
|
TRACE("oof(run jump fly grab) %d\n",p_person->Draw.Tweened->CurrentAnim);
|
|
switch(p_person->Genus.Person->PersonType) {
|
|
case PERSON_DARCI:
|
|
MFX_play_thing(THING_NUMBER(p_person),S_DARCI_HIT_END,0,p_person);
|
|
break;
|
|
case PERSON_ROPER:
|
|
MFX_play_thing(THING_NUMBER(p_person),S_ROPER_HIT_END-1,0,p_person);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
TRACE("unknown grab substate: %d\n",old_substate);
|
|
|
|
}
|
|
|
|
set_anim(p_person,ANIM_FLY_GRABBING_LEDGE);
|
|
p_person->Draw.Tweened->Angle = grab_angle;
|
|
}
|
|
|
|
//
|
|
// We have grabbed a face, so change to grab anim
|
|
//
|
|
|
|
|
|
//
|
|
// move person so new hand position is at grab_x,grab_y,grab_z
|
|
//
|
|
|
|
{
|
|
SLONG lx;
|
|
SLONG ly;
|
|
SLONG lz;
|
|
|
|
calc_sub_objects_position(p_person,0,SUB_OBJECT_LEFT_HAND,&lx,&ly,&lz);
|
|
|
|
SLONG rx;
|
|
SLONG ry;
|
|
SLONG rz;
|
|
|
|
calc_sub_objects_position(p_person,0,SUB_OBJECT_RIGHT_HAND,&rx,&ry,&rz);
|
|
|
|
new_x = lx + rx >> 1;
|
|
new_y = ly + ry >> 1;
|
|
new_z = lz + rz >> 1;
|
|
}
|
|
|
|
new_x+=p_person->WorldPos.X>>8;
|
|
new_y+=p_person->WorldPos.Y>>8;
|
|
new_z+=p_person->WorldPos.Z>>8;
|
|
|
|
MSG_add(" left hand y %d grab_y %d tween %d\n",new_y,grab_y,draw_info->AnimTween);
|
|
|
|
//LogText(" left hand pos for grab face after anim change %d %d %d \n",new_x,new_y,new_z);
|
|
|
|
//LogText(" found a ledge offset %d %d %d to it \n",grab_x-new_x,grab_y-new_y,grab_z-new_z);
|
|
|
|
temp_pos.X=((grab_x-new_x)<<8)+p_person->WorldPos.X;
|
|
temp_pos.Y=((grab_y-new_y)<<8)+p_person->WorldPos.Y;
|
|
temp_pos.Z=((grab_z-new_z)<<8)+p_person->WorldPos.Z;
|
|
|
|
if (face > 0 && (prim_faces4[face].FaceFlags & (FACE_FLAG_WMOVE|FACE_FLAG_PRIM)))
|
|
{
|
|
//
|
|
// For some mad reason- if you pull yourself up on wmove faces at
|
|
// the top of the anim you are not properly on the face...
|
|
//
|
|
|
|
temp_pos.X += -SIN(p_person->Draw.Tweened->Angle) >> 5;
|
|
temp_pos.Z += -COS(p_person->Draw.Tweened->Angle) >> 5;
|
|
}
|
|
|
|
move_thing_on_map(p_person,&temp_pos);
|
|
|
|
//
|
|
// Set the person's angle to line up with the grabbed edge.
|
|
//
|
|
|
|
|
|
// calc_sub_objects_position(p_person,0,SUB_OBJECT_LEFT_HAND,&new_x,&new_y,&new_z);
|
|
// new_x+=p_person->WorldPos.X;
|
|
// new_y+=p_person->WorldPos.Y;
|
|
// new_z+=p_person->WorldPos.Z;
|
|
//LogText(" left hand pos for grab face after anim change and adjust %d %d %d \n",new_x,new_y,new_z);
|
|
|
|
// this is perfect
|
|
|
|
//
|
|
// lock hand in place for drawing and animating
|
|
//
|
|
|
|
draw_info->Locked=SUB_OBJECT_LEFT_HAND;
|
|
// draw_info->AnimTween = C0;
|
|
if(face==GRAB_FLOOR || face == GRAB_SEWERS)
|
|
{
|
|
MSG_add("grab floor or sewers\n");
|
|
p_person->OnFace=0;
|
|
}
|
|
else
|
|
{
|
|
if(type==1)
|
|
{
|
|
p_person->Genus.Person->OnFacet=face;
|
|
p_person->OnFace=0;
|
|
}
|
|
else
|
|
{
|
|
p_person->OnFace=face;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Automatically pull yourself up if you're getting onto a moving walkable face.
|
|
//
|
|
|
|
if (face > 0 && (prim_faces4[face].FaceFlags & (FACE_FLAG_WMOVE|FACE_FLAG_PRIM)))
|
|
{
|
|
//
|
|
// Don't automatically pullup on crates.
|
|
//
|
|
|
|
if (prim_faces4[face].FaceFlags & FACE_FLAG_PRIM)
|
|
{
|
|
SLONG ob_index = -prim_faces4[face].ThingIndex;
|
|
|
|
ASSERT(WITHIN(ob_index, 1, OB_ob_upto - 1));
|
|
|
|
if (OB_ob[ob_index].prim == 129)
|
|
{
|
|
//
|
|
// Don't pull up
|
|
//
|
|
|
|
goto dont_pull_up;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Automatically do a pullup.
|
|
//
|
|
|
|
set_person_pulling_up(p_person);
|
|
|
|
dont_pull_up:;
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
void set_tween_for_dy(Thing *p_person,SLONG dy)
|
|
{
|
|
MSG_add(" tween dy %d \n",dy);
|
|
|
|
|
|
dy-=28;
|
|
|
|
if(dy>128)
|
|
dy=0;
|
|
else
|
|
if(dy<0)
|
|
dy=255;
|
|
else
|
|
dy=(128-dy)<<1;
|
|
|
|
|
|
|
|
|
|
// MSG_add("DY %d dy %d pre_shift %d \n",p_person->DY>>8,dy,y-floor_y);
|
|
p_person->Draw.Tweened->AnimTween=dy;
|
|
|
|
}
|
|
|
|
void set_tween_for_height(Thing *p_person)
|
|
{
|
|
SLONG x,y,z;
|
|
SLONG floor_y,dy;
|
|
|
|
if(p_person->DY>0)
|
|
return;
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,3,&x,&y,&z);
|
|
y+=(p_person->WorldPos.Y)>>8;
|
|
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
if (p_person->Flags & FLAGS_IN_SEWERS)
|
|
{
|
|
floor_y = NS_calc_height_at(x,z);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
floor_y = PAP_calc_height_at_thing(p_person,x,z);
|
|
}
|
|
|
|
dy=y-floor_y;
|
|
set_tween_for_dy(p_person,256+(p_person->DY>>5));
|
|
|
|
}
|
|
|
|
SLONG over_nogo(Thing *p_person)
|
|
{
|
|
SLONG mx,mz;
|
|
|
|
if(p_person->Genus.Person->Ware)
|
|
return(0);
|
|
mx=p_person->WorldPos.X>>16;
|
|
mz=p_person->WorldPos.Z>>16;
|
|
if(mx>=0&&mx<128 && mz>=0 && mz<=128)
|
|
{
|
|
if (PAP_2HI((mx)&127, (mz)&127).Flags & PAP_FLAG_NOGO)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
void fn_person_jumping(Thing *p_person)
|
|
{
|
|
SLONG end = 0,
|
|
grab = 0,
|
|
wave_id1,
|
|
wave_id2;
|
|
GameCoord new_position;
|
|
SLONG old_frame,frame;
|
|
// LogText(" person jumping substate %d\n",p_person->SubState);
|
|
// MSG_add(" JUMPING ");
|
|
//return;
|
|
|
|
SlideSoundCheck(p_person);
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_STANDING_JUMP_FORWARDS:
|
|
change_velocity_to(p_person,32); //was 25
|
|
|
|
if(over_nogo(p_person))
|
|
p_person->Velocity=0;
|
|
|
|
p_person->DeltaVelocity=0;
|
|
p_person->DY=0;
|
|
end=projectile_move_thing(p_person,1);
|
|
if(end==100)
|
|
{
|
|
//
|
|
// dead
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
if(!end)
|
|
{
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
p_person->DeltaVelocity=0;
|
|
p_person->DY=10<<8;
|
|
p_person->SubState=SUB_STATE_RUNNING_JUMP_FLY;
|
|
p_person->Genus.Person->Action=ACTION_RUN_JUMP;
|
|
if(person_has_gun_out(p_person))
|
|
{
|
|
set_locked_anim(p_person,ANIM_MID_AIR_TWEEN_LEFT_AK,0);
|
|
}
|
|
else
|
|
{
|
|
set_locked_anim(p_person,ANIM_MID_AIR_TWEEN_LEFT,0);
|
|
}
|
|
p_person->Draw.Tweened->NextFrame=global_anim_array[p_person->Genus.Person->AnimType][ANIM_MID_AIR_TWEEN_LEFT];
|
|
|
|
}
|
|
}
|
|
|
|
grab=grab_ledge(p_person);
|
|
/*
|
|
if((end==1)&&!grab)
|
|
{
|
|
set_person_idle(p_person);
|
|
// plant_feet(p_person);
|
|
}
|
|
*/
|
|
|
|
break;
|
|
case SUB_STATE_STANDING_JUMP_BACKWARDS:
|
|
change_velocity_to(p_person,-32); //was 25
|
|
if(over_nogo(p_person))
|
|
p_person->Velocity=0;
|
|
|
|
p_person->DeltaVelocity=0;
|
|
p_person->DY=0;
|
|
if(p_person->Draw.Tweened->FrameIndex>2)
|
|
{
|
|
if(p_person->Draw.Tweened->FrameIndex>4)
|
|
end=projectile_move_thing(p_person,3);
|
|
else
|
|
end=projectile_move_thing(p_person,1);
|
|
if(end==100)
|
|
{
|
|
//
|
|
// dead
|
|
//
|
|
|
|
return;
|
|
}
|
|
if(end==1)
|
|
{
|
|
set_person_idle(p_person);
|
|
// plant_feet(p_person);
|
|
return;
|
|
}
|
|
else
|
|
if(end==2)
|
|
{
|
|
set_person_drop_down(p_person,0);
|
|
p_person->Velocity = 0;
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
end=0;
|
|
}
|
|
|
|
if(!end)
|
|
end=person_normal_animate(p_person);
|
|
|
|
// grab=grab_ledge(p_person);
|
|
|
|
if(end==1)
|
|
{
|
|
set_person_drop_down(p_person,0);
|
|
p_person->DY=-20<<8;
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
case SUB_STATE_STANDING_JUMP:
|
|
MSG_add(" standing jump ");
|
|
end=person_normal_animate(p_person);
|
|
grab=grab_ledge(p_person);
|
|
SLONG pinnacle_frame;
|
|
|
|
switch(p_person->Genus.Person->AnimType)
|
|
{
|
|
case ANIM_TYPE_ROPER:
|
|
pinnacle_frame=5;
|
|
break;
|
|
default: // darci, others
|
|
pinnacle_frame=3;
|
|
}
|
|
// if(p_person->Draw.Tweened->FrameIndex>pinnacle_frame && !grab)
|
|
if(end && !grab)
|
|
{
|
|
set_person_drop_down(p_person,PERSON_DROP_DOWN_KEEP_VEL|PERSON_DROP_DOWN_QUEUED);
|
|
}
|
|
else
|
|
{
|
|
if(end==1)
|
|
{
|
|
MSG_add("end standing jump anim");
|
|
}
|
|
if(grab)
|
|
{
|
|
MSG_add("grab standing jump");
|
|
|
|
}
|
|
|
|
if((end==1)&&!grab)
|
|
{
|
|
set_person_idle(p_person);
|
|
person_splash(p_person, -1);
|
|
}
|
|
|
|
if(p_person->Draw.Tweened->FrameIndex==4)
|
|
{
|
|
wave_id1 = footstep_wave(p_person);
|
|
wave_id2 = footstep_wave(p_person);
|
|
// play_quick_wave(p_person,wave_id1,WAVE_PLAY_INTERUPT);
|
|
// play_quick_wave(p_person,wave_id2,WAVE_PLAY_OVERLAP);
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id1,MFX_REPLACE,p_person);
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id2,MFX_REPLACE,p_person);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_RUNNING_JUMP:
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
SLONG reqd_vel=(50*15)/20;
|
|
if(p_person->Velocity<(50*15)/20)
|
|
p_person->Velocity=(50*15)/20;
|
|
else
|
|
if(p_person->Velocity>(60*15)/20)
|
|
p_person->Velocity=(60*15)/20;
|
|
|
|
|
|
//set_thing_velocity(p_person,50); //32); //was 25
|
|
}
|
|
if(over_nogo(p_person))
|
|
p_person->Velocity=0;
|
|
|
|
p_person->DeltaVelocity=0;
|
|
end=projectile_move_thing(p_person,1);
|
|
if(end==100)
|
|
{
|
|
//
|
|
// dead
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
old_frame=p_person->Draw.Tweened->FrameIndex;
|
|
|
|
if(old_frame<3)
|
|
{
|
|
if(check_on_slippy_slope(p_person))
|
|
return;
|
|
}
|
|
if(!end)
|
|
end=person_normal_animate(p_person);
|
|
frame=p_person->Draw.Tweened->FrameIndex;
|
|
|
|
p_person->DY=0;
|
|
|
|
grab=grab_ledge(p_person);
|
|
if(grab)
|
|
{
|
|
MSG_add(" running jump grabbed 1\n");
|
|
}
|
|
if(!grab)
|
|
{
|
|
if(end==1) //phase 1 anim end
|
|
{
|
|
p_person->Draw.Tweened->Locked=0;//
|
|
|
|
p_person->Flags|=FLAGS_PROJECTILE_MOVEMENT;
|
|
p_person->DeltaVelocity=0;
|
|
p_person->DY=10<<8;
|
|
p_person->SubState=SUB_STATE_RUNNING_JUMP_FLY;
|
|
p_person->Genus.Person->Action=ACTION_RUN_JUMP;
|
|
// PlaySample(THING_NUMBER(p_person),SAMPLE_WOMAN_JUMP1,SAMPLE_VOL_MAX,SAMPLE_PAN_CENTER,SAMPLE_FREQ_ORIG,0);
|
|
if(person_has_gun_out(p_person))
|
|
{
|
|
p_person->Draw.Tweened->NextFrame=global_anim_array[p_person->Genus.Person->AnimType][ANIM_MID_AIR_TWEEN_LEFT_AK];
|
|
}
|
|
else
|
|
{
|
|
p_person->Draw.Tweened->NextFrame=global_anim_array[p_person->Genus.Person->AnimType][ANIM_MID_AIR_TWEEN_LEFT];
|
|
}
|
|
|
|
/*
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_RUN_JUMP_LEFT:
|
|
p_person->Draw.Tweened->NextFrame=global_anim_array[p_person->Genus.Person->AnimType][ANIM_MID_AIR_TWEEN_LEFT];
|
|
break;
|
|
|
|
case ANIM_RUN_JUMP_RIGHT:
|
|
p_person->Draw.Tweened->NextFrame=global_anim_array[p_person->Genus.Person->AnimType][ANIM_MID_AIR_TWEEN_RIGHT];
|
|
break;
|
|
|
|
default:
|
|
p_person->Draw.Tweened->NextFrame=global_anim_array[p_person->Genus.Person->AnimType][ANIM_MID_AIR_LAND];
|
|
break;
|
|
|
|
|
|
}
|
|
*/
|
|
p_person->Draw.Tweened->AnimTween=0;
|
|
|
|
}
|
|
}
|
|
break;
|
|
case SUB_STATE_RUNNING_JUMP_FLY_STOP:
|
|
change_velocity_to(p_person,0); //25
|
|
goto jump_fly;
|
|
|
|
case SUB_STATE_RUNNING_JUMP_FLY:
|
|
if(continue_moveing(p_person)&&!over_nogo(p_person))
|
|
{
|
|
// change_velocity_to(p_person,50); //32); //25
|
|
}
|
|
else
|
|
{
|
|
set_person_drop_down(p_person,PERSON_DROP_DOWN_KEEP_VEL|PERSON_DROP_DOWN_KEEP_DY|PERSON_DROP_DOWN_QUEUED);
|
|
p_person->Velocity>>=1;
|
|
return;
|
|
}
|
|
//change_velocity_to(p_person,0); //25
|
|
|
|
// set_thing_velocity(p_person,32); //25
|
|
jump_fly:;
|
|
|
|
if (p_person->Draw.Tweened->CurrentAnim == ANIM_PLUNGE_START ||
|
|
p_person->Draw.Tweened->CurrentAnim == ANIM_PLUNGE_FORWARDS)
|
|
{
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end == 1)
|
|
{
|
|
if (p_person->Draw.Tweened->CurrentAnim == ANIM_PLUNGE_START)
|
|
{
|
|
locked_anim_change(p_person, SUB_OBJECT_PELVIS, ANIM_PLUNGE_FORWARDS);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
set_tween_for_height(p_person);
|
|
}
|
|
|
|
end = projectile_move_thing(p_person,3);
|
|
|
|
if(end==100)
|
|
{
|
|
//
|
|
// dead
|
|
//
|
|
|
|
return;
|
|
}
|
|
// if(!end)
|
|
// person_normal_animate(p_person);
|
|
|
|
grab=grab_ledge(p_person);
|
|
if(grab)
|
|
{
|
|
MSG_add("grab face in running jump fly \n");
|
|
if(end==2)
|
|
{
|
|
MSG_add(" hit fence, but grabbed something as well");
|
|
}
|
|
|
|
// p_person->SubState=0;
|
|
}
|
|
else
|
|
if(end==1)
|
|
{
|
|
p_person->Genus.Person->Action=ACTION_LANDING;
|
|
person_splash(p_person, -1);
|
|
|
|
//
|
|
// If end == 1, then we are about to land on the floor or on a
|
|
// face... it depends on whether the p_person's OnFace field is set or not.
|
|
//
|
|
|
|
DrawTween *draw_info;
|
|
|
|
draw_info = p_person->Draw.Tweened;
|
|
if(continue_moveing(p_person))
|
|
{
|
|
//
|
|
// player wishes to land and continue running
|
|
//
|
|
if(person_has_gun_out(p_person))
|
|
{
|
|
set_locked_anim(p_person,ANIM_LAND_RIGHT_AK,SUB_OBJECT_RIGHT_FOOT);
|
|
}
|
|
else
|
|
{
|
|
set_locked_anim(p_person,ANIM_LAND_RIGHT,SUB_OBJECT_RIGHT_FOOT);
|
|
}
|
|
/*
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_RUN_JUMP_LEFT:
|
|
set_locked_anim(p_person,ANIM_LAND_RIGHT,SUB_OBJECT_RIGHT_FOOT);
|
|
break;
|
|
|
|
case ANIM_RUN_JUMP_RIGHT:
|
|
set_locked_anim(p_person,ANIM_LAND_LEFT,SUB_OBJECT_LEFT_FOOT);
|
|
break;
|
|
}
|
|
*/
|
|
// set_locked_anim(p_person,ANIM_LAND_RUN,SUB_OBJECT_LEFT_FOOT);
|
|
// plant_feet(p_person);
|
|
|
|
if(p_person->OnFace==0)
|
|
{
|
|
/*
|
|
if (p_person->Flags & FLAGS_IN_SEWERS)
|
|
{
|
|
p_person->WorldPos.Y=NS_calc_height_at(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<<8;
|
|
}
|
|
else
|
|
{
|
|
p_person->WorldPos.Y=PAP_calc_height_at(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<<8;
|
|
}
|
|
*/
|
|
//already set
|
|
// p_person->WorldPos.Y=PAP_calc_height_at_thing(p_person,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<<8;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
#ifdef NOT_SETUP_IN_PROJECTILE
|
|
some old tat
|
|
SLONG new_y,face;
|
|
/*
|
|
calc_sub_objects_position(
|
|
p_thing,
|
|
255, //p_thing->Draw.Tweened->AnimTween,
|
|
pelvis?0:SUB_OBJECT_LEFT_FOOT,
|
|
&fx,
|
|
&fy,
|
|
&fz);
|
|
*/
|
|
|
|
|
|
MSG_add("wp y %d \n",p_person->WorldPos.Y>>8);
|
|
face = find_face_for_this_pos(p_person->WorldPos.X>>8,p_person->WorldPos.Y>>8,p_person->WorldPos.Z>>8,&new_y,0,0);
|
|
|
|
if(face==0)
|
|
{
|
|
ASSERT(0);
|
|
face = find_face_for_this_pos(p_person->WorldPos.X>>8,p_person->WorldPos.Y>>8,p_person->WorldPos.Z>>8,&new_y,0,0);
|
|
|
|
}
|
|
MSG_add(" hit face while jumping, try to find face= %d newy %d \n",face,new_y);
|
|
//ASSERT(face!=GRAB_FACE);
|
|
/*
|
|
if(new_y==1000000)
|
|
{
|
|
ASSERT(0);
|
|
p_person->OnFace=0;
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
// ASSERT(face);//triggered
|
|
p_person->OnFace=face;
|
|
p_person->WorldPos.Y=new_y<<8;
|
|
}
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
p_person->SubState = SUB_STATE_RUNNING_JUMP_LAND_FAST;
|
|
p_person->Genus.Person->Action = ACTION_RUN;
|
|
|
|
LogText("cm1 calc landing y again %d \n",p_person->WorldPos.Y);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// player has stopped pressing forward and wants to just land and be idle
|
|
//
|
|
set_locked_anim(p_person,ANIM_LAND_STAND,0);
|
|
|
|
if(p_person->OnFace==0)
|
|
{
|
|
/*
|
|
if (p_person->Flags & FLAGS_IN_SEWERS)
|
|
{
|
|
p_person->WorldPos.Y=NS_calc_height_at(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<<8;
|
|
}
|
|
else
|
|
{
|
|
p_person->WorldPos.Y=PAP_calc_height_at(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<<8;
|
|
}
|
|
*/
|
|
// already set
|
|
//p_person->WorldPos.Y=PAP_calc_height_at_thing(p_person,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<<8; //md021199
|
|
}
|
|
else
|
|
{
|
|
|
|
SLONG new_y,face;
|
|
face = find_face_for_this_pos(p_person->WorldPos.X>>8,p_person->WorldPos.Y>>8,p_person->WorldPos.Z>>8,&new_y,0,0);
|
|
// ASSERT(face!=GRAB_FACE)
|
|
/*
|
|
if(new_y==1000000)
|
|
{
|
|
ASSERT(0);
|
|
p_person->OnFace=0;
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
ASSERT(face);
|
|
p_person->OnFace=face;
|
|
//alreadyset
|
|
//p_person->WorldPos.Y=new_y<<8; //md021199
|
|
}
|
|
|
|
}
|
|
|
|
// p_person->SubState = SUB_STATE_RUNNING_JUMP_LAND;
|
|
|
|
set_person_idle(p_person);
|
|
// plant_feet(p_person);
|
|
LogText("cm2 calc landing y again %d \n",p_person->WorldPos.Y);
|
|
}
|
|
|
|
draw_info->AnimTween = 0;
|
|
// PlaySample(THING_NUMBER(p_person),SAMPLE_WOMAN_LAND1,SAMPLE_VOL_MAX,SAMPLE_PAN_CENTER,SAMPLE_FREQ_ORIG+(GAME_TURN&0xfff),0);
|
|
}
|
|
else
|
|
if(end==2)
|
|
{
|
|
MSG_add(" hit fence, so hold on");
|
|
}
|
|
else
|
|
{
|
|
|
|
//if(p_person->Draw.Tweened->AnimTween<64)
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_REQUEST_KICK)
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_KICK;
|
|
set_anim(p_person,ANIM_FLYKICK_START);
|
|
p_person->SubState=SUB_STATE_FLYING_KICK;
|
|
|
|
}
|
|
|
|
}
|
|
break;
|
|
case SUB_STATE_FLYING_KICK:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
queue_anim(p_person,ANIM_FLYKICK_FALL);
|
|
p_person->SubState=SUB_STATE_FLYING_KICK_FALL;
|
|
}
|
|
//
|
|
// fall through into next case
|
|
//
|
|
case SUB_STATE_FLYING_KICK_FALL:
|
|
end=person_normal_animate(p_person);
|
|
if(over_nogo(p_person))
|
|
p_person->Velocity=0;
|
|
end=projectile_move_thing(p_person,3);
|
|
if(end==100)
|
|
{
|
|
//
|
|
// dead
|
|
//
|
|
|
|
return;
|
|
}
|
|
else
|
|
if(end==1)
|
|
{
|
|
p_person->Genus.Person->Action=ACTION_LANDING;
|
|
person_splash(p_person, -1);
|
|
|
|
//
|
|
// If end == 1, then we are about to land on the floor or on a
|
|
// face... it depends on whether the p_person's OnFace field is set or not.
|
|
//
|
|
|
|
DrawTween *draw_info;
|
|
|
|
draw_info = p_person->Draw.Tweened;
|
|
{
|
|
//
|
|
// player wishes to land and continue running
|
|
//
|
|
set_locked_anim(p_person,ANIM_FLYKICK_LAND,SUB_OBJECT_RIGHT_FOOT);
|
|
|
|
if(p_person->OnFace==0)
|
|
{
|
|
p_person->WorldPos.Y=PAP_calc_height_at_thing(p_person,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8)<<8;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
p_person->SubState = SUB_STATE_RUNNING_JUMP_LAND_FAST;
|
|
LogText("cm1 calc landing y again %d \n",p_person->WorldPos.Y);
|
|
}
|
|
|
|
draw_info->AnimTween = 0;
|
|
}
|
|
break;
|
|
|
|
|
|
break;
|
|
case SUB_STATE_RUNNING_JUMP_LAND:
|
|
MSG_add("RJ LANDING ");
|
|
change_velocity_to(p_person,yomp_speed); //32); //25
|
|
if(over_nogo(p_person))
|
|
p_person->Velocity=0;
|
|
end=projectile_move_thing(p_person,3);
|
|
if(end==100)
|
|
{
|
|
//
|
|
// dead
|
|
//
|
|
|
|
return;
|
|
}
|
|
// person_normal_move(p_person);
|
|
if(end)
|
|
{
|
|
set_person_idle(p_person);
|
|
// plant_feet(p_person);
|
|
// calc_camera_pos(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_RUNNING_JUMP_LAND_FAST:
|
|
|
|
// while(!Keys[KB_E]&&SHELL_ACTIVE);
|
|
MSG_add("RJ LANDING FAST");
|
|
// change_velocity_to(p_person,5);
|
|
// person_normal_move(p_person);
|
|
change_velocity_to(p_person,yomp_speed); //32); //25
|
|
if(over_nogo(p_person))
|
|
p_person->Velocity=0;
|
|
person_normal_move(p_person);
|
|
|
|
if(p_person->SubState!=SUB_STATE_RUNNING_JUMP_LAND_FAST)
|
|
{
|
|
p_person->DY=-4001;
|
|
return;
|
|
|
|
}
|
|
end=person_normal_animate(p_person);
|
|
|
|
// if(p_person->Draw.Tweened->NextFrame)
|
|
// if(p_person->Draw.Tweened->NextFrame->NextFrame==0)
|
|
if(end||!continue_moveing(p_person))
|
|
{
|
|
SLONG anim;
|
|
|
|
anim=get_yomp_anim(p_person);
|
|
|
|
set_anim(p_person,anim); //was locked //Miked aug 2000
|
|
set_generic_person_state_function(p_person,STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_RUNNING;
|
|
p_person->Genus.Person->Action = ACTION_RUN;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
/*
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_LAND_LEFT:
|
|
set_person_running(p_person);
|
|
break;
|
|
case ANIM_LAND_RIGHT:
|
|
set_person_running_frame(p_person,3);
|
|
break;
|
|
|
|
|
|
}
|
|
*/
|
|
|
|
wave_id1 = footstep_wave(p_person);
|
|
wave_id2 = footstep_wave(p_person);
|
|
// play_quick_wave(p_person,wave_id1,WAVE_PLAY_INTERUPT);
|
|
// play_quick_wave(p_person,wave_id2,WAVE_PLAY_OVERLAP);
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id1,MFX_REPLACE,p_person);
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id2,MFX_REPLACE,p_person);
|
|
|
|
// set_thing_velocity(p_person,48); //25
|
|
}
|
|
//p_person->Draw.Tweened->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_RUN];
|
|
/*
|
|
if(end)
|
|
{
|
|
set_person_running(p_person);
|
|
p_person->Draw.Tweened->QueuedFrame = 0; //global_anim_array[p_person->Genus.Person->AnimType][ANIM_RUN];
|
|
set_thing_velocity(p_person,25);
|
|
// calc_camera_pos(p_person);
|
|
}
|
|
*/
|
|
break;
|
|
default:
|
|
MSG_add("JUMPING unknow substate %d \n",p_person->SubState);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
void position_person_at_ladder_top(Thing *p_person,SLONG limb)
|
|
{
|
|
SLONG x1,y1,z1;
|
|
SLONG x[2],z[2],y,wall;
|
|
struct DFacet *p_facet;
|
|
SLONG top;
|
|
|
|
p_facet=&dfacets[p_person->Genus.Person->OnFacet];
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,limb,&x1,&y1,&z1);
|
|
|
|
y1+=p_person->WorldPos.Y>>8;
|
|
|
|
top = p_facet->Y[0] + p_facet->Height * 64;
|
|
y1-=top-20;
|
|
|
|
//
|
|
// y1 is difference between position of Right Hand on ladder, and top of ladder.
|
|
//
|
|
|
|
// y1=0;
|
|
|
|
|
|
p_person->WorldPos.Y-=y1<<8;
|
|
}
|
|
|
|
void position_person_at_ladder_bot(Thing *p_person,SLONG limb)
|
|
{
|
|
SLONG x1,y1,z1;
|
|
SLONG x[2],z[2],y,wall;
|
|
struct DFacet *p_facet;
|
|
SLONG bot;
|
|
|
|
p_facet=&dfacets[p_person->Genus.Person->OnFacet];
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,limb,&x1,&y1,&z1);
|
|
|
|
y1+=p_person->WorldPos.Y>>8;
|
|
|
|
bot = p_facet->Y[0]; // + p_facet->Height * 64;
|
|
y1-=bot;
|
|
|
|
//
|
|
// y1 is difference between position of Right Hand on ladder, and top of ladder.
|
|
//
|
|
|
|
// y1=0;
|
|
|
|
|
|
p_person->WorldPos.Y=bot<<8; //y1<<8;
|
|
}
|
|
|
|
//
|
|
// Returns a bit field to indicate where on the ladder the sub-part is.
|
|
//
|
|
|
|
#define PERSON_LIMB_ON_LADDER (1 << 0)
|
|
#define PERSON_LIMB_TOP_BLOCK (1 << 1)
|
|
#define PERSON_LIMB_BOT_BLOCK (1 << 2)
|
|
#define PERSON_LIMB_OFF_TOP (1 << 3)
|
|
#define PERSON_LIMB_OFF_BOT (1 << 4)
|
|
|
|
ULONG check_limb_pos_on_ladder(Thing *p_person,SLONG sub_part, SLONG i_am_going_down)
|
|
{
|
|
SLONG x1,y1,z1;
|
|
UWORD facet;
|
|
SLONG x[2],z[2],y,wall;
|
|
SLONG top;
|
|
SLONG bot;
|
|
ULONG ans;
|
|
|
|
struct DFacet *p_facet;
|
|
|
|
facet=p_person->Genus.Person->OnFacet;
|
|
|
|
p_facet=&dfacets[facet];
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,sub_part,&x1,&y1,&z1);
|
|
|
|
x1 += p_person->WorldPos.X>>8;
|
|
y1 += p_person->WorldPos.Y>>8;
|
|
z1 += p_person->WorldPos.Z>>8;
|
|
|
|
x[0] = p_facet->x[0] << 8;
|
|
z[0] = p_facet->z[0] << 8;
|
|
|
|
x[1] = p_facet->x[1] << 8;
|
|
z[1] = p_facet->z[1] << 8;
|
|
|
|
bot = p_facet->Y[0];
|
|
|
|
top = bot + p_facet->Height * 64;
|
|
|
|
ans = 0;
|
|
|
|
if (WITHIN(y1, bot + ((i_am_going_down) ? 20 : 0), top - 20))
|
|
{
|
|
ans |= PERSON_LIMB_ON_LADDER;
|
|
|
|
if (y1 > top - 256) {ans |= PERSON_LIMB_TOP_BLOCK;}
|
|
if (y1 < bot + 256) {ans |= PERSON_LIMB_BOT_BLOCK;}
|
|
}
|
|
else
|
|
{
|
|
if (y1 < bot + 20) {ans |= PERSON_LIMB_OFF_BOT;}
|
|
if (y1 > top + 20) {ans |= PERSON_LIMB_OFF_TOP;}
|
|
}
|
|
|
|
return ans;
|
|
}
|
|
|
|
|
|
|
|
SLONG check_limb_pos_on_fence(Thing *p_person,SLONG sub_part)
|
|
{
|
|
SLONG x1,y1,z1;
|
|
SLONG col;
|
|
SLONG top,bottom;
|
|
SLONG x,z;
|
|
|
|
//
|
|
// The top and bottom of the fence.
|
|
//
|
|
|
|
x = p_person->WorldPos.X >> 8;
|
|
z = p_person->WorldPos.Z >> 8;
|
|
col = p_person->Genus.Person->OnFacet;
|
|
|
|
top = get_fence_top (x,z,col);
|
|
bottom = get_fence_bottom(x,z,col);
|
|
|
|
//
|
|
// The position of our limb.
|
|
//
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,sub_part,&x1,&y1,&z1);
|
|
|
|
y1 += p_person->WorldPos.Y>>8;
|
|
|
|
//
|
|
// The limb counts as being on the fence only if it is not too near the bottom.
|
|
//
|
|
|
|
if (WITHIN(y1, bottom + 20, top))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
SLONG check_limb_pos_on_fence_sideways(Thing *p_person,SLONG sub_part)
|
|
{
|
|
SLONG x1,y1,z1;
|
|
SLONG col;
|
|
SLONG along;
|
|
|
|
col=p_person->Genus.Person->OnFacet;
|
|
|
|
SLONG calc_along_vect(SLONG ax,SLONG az,struct DFacet *p_vect);
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,sub_part,&x1,&y1,&z1);
|
|
|
|
x1+=p_person->WorldPos.X>>8;
|
|
z1+=p_person->WorldPos.Z>>8;
|
|
|
|
along=calc_along_vect(x1,z1,&dfacets[col]);
|
|
|
|
if(along<=0 || along>=255)
|
|
{
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void fn_person_laddering(Thing *p_person)
|
|
{
|
|
BOOL play_it = FALSE;
|
|
UBYTE last_frame;
|
|
SLONG end=0,hit,
|
|
foot_step_wave;
|
|
WaveParams foot_step;
|
|
ULONG on_ladder,on_ladder_left,on_ladder_right;
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_MOUNT_LADDER:
|
|
last_frame = p_person->Draw.Tweened->FrameIndex;
|
|
end = person_normal_animate(p_person);
|
|
if(p_person->Draw.Tweened->FrameIndex!=last_frame && p_person->Draw.Tweened->FrameIndex==3)
|
|
play_it = TRUE;
|
|
|
|
if(end==1)
|
|
{
|
|
set_person_on_ladder(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_ON_LADDER:
|
|
case SUB_STATE_STOPPING:
|
|
break;
|
|
case SUB_STATE_CLIMB_UP_LADDER:
|
|
|
|
on_ladder_left = check_limb_pos_on_ladder(p_person,SUB_OBJECT_LEFT_HAND, FALSE);
|
|
on_ladder_right= check_limb_pos_on_ladder(p_person,SUB_OBJECT_RIGHT_HAND, FALSE);
|
|
|
|
if ((on_ladder_left&on_ladder_right) & PERSON_LIMB_ON_LADDER)
|
|
{
|
|
last_frame = p_person->Draw.Tweened->FrameIndex;
|
|
end = person_normal_animate(p_person);
|
|
if(p_person->Draw.Tweened->FrameIndex!=last_frame && ((p_person->Draw.Tweened->FrameIndex%3==0) || (p_person->Draw.Tweened->FrameIndex%6==0)))
|
|
play_it = TRUE;
|
|
|
|
if(end==1)
|
|
{
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
locked_anim_change_height_type(p_person,SUB_OBJECT_LEFT_HAND,COP_ROPER_ANIM_LADDER_LOOP,p_person->Genus.Person->AnimType);
|
|
else
|
|
// if(p_person->Genus.Person->PersonType==PERSON_COP)
|
|
if(p_person->Genus.Person->PersonType==PERSON_COP||p_person->Genus.Person->PersonType==PERSON_THUG_GREY||p_person->Genus.Person->PersonType==PERSON_THUG_RASTA||p_person->Genus.Person->PersonType==PERSON_THUG_RED)
|
|
locked_anim_change_height_type(p_person,SUB_OBJECT_LEFT_HAND,COP_ROPER_ANIM_LADDER_LOOP,ANIM_TYPE_ROPER);
|
|
else
|
|
locked_anim_change_height_type(p_person,SUB_OBJECT_LEFT_HAND,ANIM_ON_LADDER,ANIM_TYPE_DARCI);
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
}
|
|
|
|
/*
|
|
|
|
if (p_person->Flags & FLAGS_IN_SEWERS)
|
|
{
|
|
SLONG ladder = p_person->Genus.Person->OnFacet;
|
|
DFacet *df;
|
|
|
|
ASSERT(WITHIN(ladder, 1, next_dfacet - 1));
|
|
ASSERT(dfacets[ladder].FacetType == STOREY_TYPE_LADDER);
|
|
|
|
//
|
|
// If this person is climbing out of a sewer...
|
|
//
|
|
|
|
df = &dfacets[ladder];
|
|
|
|
if (df->FacetFlags & FACET_FLAG_LADDER_LINK)
|
|
{
|
|
if ((on_ladder_left|on_ladder_right) & PERSON_LIMB_TOP_BLOCK)
|
|
{
|
|
//
|
|
// Make the person leave the sewers.
|
|
//
|
|
|
|
p_person->Flags &= ~FLAGS_IN_SEWERS;
|
|
}
|
|
}
|
|
}
|
|
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Climb off top of ladder
|
|
//
|
|
p_person->SubState=SUB_STATE_CLIMB_OFF_LADDER_TOP;
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
set_anim_of_type(p_person,COP_ROPER_ANIM_LADDER_END_L,ANIM_TYPE_ROPER);
|
|
else
|
|
if(p_person->Genus.Person->PersonType==PERSON_COP||p_person->Genus.Person->PersonType==PERSON_THUG_GREY||p_person->Genus.Person->PersonType==PERSON_THUG_RASTA||p_person->Genus.Person->PersonType==PERSON_THUG_RED)
|
|
set_anim_of_type(p_person,COP_ROPER_ANIM_LADDER_END_L,ANIM_TYPE_ROPER);
|
|
else
|
|
set_anim(p_person,ANIM_OFF_LADDER_TOP);
|
|
|
|
if(on_ladder_left)
|
|
position_person_at_ladder_top(p_person,SUB_OBJECT_RIGHT_HAND);
|
|
else
|
|
position_person_at_ladder_top(p_person,SUB_OBJECT_LEFT_HAND);
|
|
p_person->Genus.Person->Action=ACTION_CLIMBING;
|
|
}
|
|
/*
|
|
if(--p_person->Genus.Person->Timer1==0)
|
|
{
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
*/
|
|
|
|
break;
|
|
case SUB_STATE_CLIMB_DOWN_ONTO_LADDER:
|
|
end = person_backwards_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
set_person_on_ladder(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_CLIMB_DOWN_LADDER:
|
|
|
|
on_ladder_left =check_limb_pos_on_ladder(p_person,SUB_OBJECT_LEFT_FOOT, TRUE);
|
|
on_ladder_right=check_limb_pos_on_ladder(p_person,SUB_OBJECT_RIGHT_FOOT, TRUE);
|
|
|
|
if ((on_ladder_left&on_ladder_right) & PERSON_LIMB_ON_LADDER)
|
|
{
|
|
last_frame = p_person->Draw.Tweened->FrameIndex;
|
|
end = person_backwards_animate(p_person);
|
|
if(p_person->Draw.Tweened->FrameIndex!=last_frame && ((p_person->Draw.Tweened->FrameIndex%3==0) || (p_person->Draw.Tweened->FrameIndex%6==0)))
|
|
play_it = TRUE;
|
|
|
|
if(end==1)
|
|
{
|
|
MSG_add(" LOCKED CHANGE END \n");
|
|
p_person->Draw.Tweened->AnimTween=0;
|
|
if(p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
locked_anim_change_end_type(p_person,SUB_OBJECT_LEFT_HAND,COP_ROPER_ANIM_LADDER_LOOP,p_person->Genus.Person->AnimType);
|
|
else
|
|
// if(p_person->Genus.Person->PersonType==PERSON_COP)
|
|
if(p_person->Genus.Person->PersonType==PERSON_COP||p_person->Genus.Person->PersonType==PERSON_THUG_GREY||p_person->Genus.Person->PersonType==PERSON_THUG_RASTA||p_person->Genus.Person->PersonType==PERSON_THUG_RED)
|
|
locked_anim_change_end_type(p_person,SUB_OBJECT_LEFT_HAND,COP_ROPER_ANIM_LADDER_LOOP,ANIM_TYPE_ROPER);
|
|
else
|
|
locked_anim_change_end_type(p_person,SUB_OBJECT_LEFT_HAND,ANIM_ON_LADDER,p_person->Genus.Person->AnimType);
|
|
|
|
// locked_anim_change_end(p_person,SUB_OBJECT_LEFT_HAND,ANIM_ON_LADDER);
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
|
|
/*
|
|
if (p_person->Flags & FLAGS_IN_SEWERS)
|
|
{
|
|
SLONG ladder = p_person->Genus.Person->OnFacet;
|
|
DFacet *df;
|
|
|
|
ASSERT(WITHIN(ladder, 1, next_dfacet - 1));
|
|
ASSERT(dfacets[ladder].FacetType == STOREY_TYPE_LADDER);
|
|
|
|
//
|
|
// If this person is climbing into a sewer...
|
|
//
|
|
|
|
df = &dfacets[ladder];
|
|
|
|
if (df->FacetFlags & FACET_FLAG_LADDER_LINK)
|
|
{
|
|
if (!(on_ladder_left & PERSON_LIMB_TOP_BLOCK))
|
|
{
|
|
//
|
|
// Make the person enter the sewers.
|
|
//
|
|
|
|
p_person->Flags |= FLAGS_IN_SEWERS;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// climb off bottom of ladder
|
|
//
|
|
p_person->SubState=SUB_STATE_CLIMB_OFF_LADDER_BOT;
|
|
set_anim(p_person,ANIM_OFF_LADDER_BOT);
|
|
position_person_at_ladder_bot(p_person,SUB_OBJECT_LEFT_FOOT);
|
|
|
|
p_person->Genus.Person->Action=ACTION_CLIMBING;
|
|
}
|
|
/*
|
|
if(--p_person->Genus.Person->Timer1==0)
|
|
{
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
*/
|
|
break;
|
|
case SUB_STATE_CLIMB_OFF_LADDER_BOT:
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
//p_person->OnFace=0;
|
|
set_person_idle(p_person);
|
|
//set_anim(p_person,ANIM_OFF_LADDER_TOP);
|
|
p_person->Draw.Tweened->CurrentFrame=p_person->Draw.Tweened->QueuedFrame;
|
|
p_person->Draw.Tweened->NextFrame=p_person->Draw.Tweened->QueuedFrame;
|
|
p_person->Draw.Tweened->QueuedFrame=0;
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_STAND_READY);
|
|
plant_feet(p_person);
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_CLIMB_OFF_LADDER_TOP:
|
|
last_frame = p_person->Draw.Tweened->FrameIndex;
|
|
end = person_normal_animate(p_person);
|
|
if(p_person->Draw.Tweened->FrameIndex!=last_frame && (p_person->Draw.Tweened->FrameIndex==1 || p_person->Draw.Tweened->FrameIndex==3))
|
|
play_it = TRUE;
|
|
|
|
if(end==1)
|
|
{
|
|
person_bodge_forward(p_person,40);
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_STAND_READY);
|
|
plant_feet(p_person);
|
|
if(p_person->State!=STATE_DANGLING)
|
|
set_person_idle(p_person);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
MSG_add("LADDERING unknow substate %d \n",p_person->SubState);
|
|
break;
|
|
}
|
|
if(play_it)
|
|
{
|
|
foot_step_wave = ((Random()*(S_FOOTS_RUNG_END-S_FOOTS_RUNG_START))>>16)+S_FOOTS_RUNG_START;
|
|
//play_quick_wave(p_person,foot_step_wave,WAVE_PLAY_NO_INTERUPT);
|
|
MFX_play_thing(THING_NUMBER(p_person),foot_step_wave,MFX_OVERLAP,p_person);
|
|
}
|
|
}
|
|
|
|
void fn_person_climbing(Thing *p_person)
|
|
{
|
|
SLONG end,hit;
|
|
SLONG left_foot,right_foot;
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_CLIMB_LANDING:
|
|
//LogText(" stand to mount ladder \n");
|
|
|
|
end=person_normal_animate(p_person);
|
|
|
|
if (end==1)
|
|
{
|
|
if (p_person->Genus.Person->AnimType!=ANIM_TYPE_ROPER)
|
|
queue_anim(p_person,ANIM_LANDED_ON_FENCE);
|
|
p_person->SubState=SUB_STATE_CLIMB_LANDING2;
|
|
|
|
{
|
|
//
|
|
// If this is an electric fence... then fall off the fence and
|
|
// create electricity between the fence and the person...
|
|
//
|
|
|
|
if (p_person->Genus.Person->OnFacet > 0)
|
|
{
|
|
SLONG col = p_person->Genus.Person->OnFacet;
|
|
|
|
if (col > 0)
|
|
{
|
|
if (dfacets[col].FacetFlags & FACET_FLAG_ELECTRIFIED)
|
|
{
|
|
SLONG i;
|
|
|
|
SLONG px;
|
|
SLONG py;
|
|
SLONG pz;
|
|
#ifndef PSX
|
|
SPARK_Pinfo p1;
|
|
SPARK_Pinfo p2;
|
|
|
|
UBYTE limb[4] =
|
|
{
|
|
SUB_OBJECT_LEFT_FOOT,
|
|
SUB_OBJECT_LEFT_HAND,
|
|
SUB_OBJECT_RIGHT_FOOT,
|
|
SUB_OBJECT_RIGHT_HAND
|
|
};
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
limb[i],
|
|
&px,
|
|
&py,
|
|
&pz);
|
|
|
|
px += p_person->WorldPos.X >> 8;
|
|
py += p_person->WorldPos.Y >> 8;
|
|
pz += p_person->WorldPos.Z >> 8;
|
|
|
|
p1.type = SPARK_TYPE_LIMB;
|
|
p1.flag = 0;
|
|
p1.person = THING_NUMBER(p_person);
|
|
p1.limb = limb[i];
|
|
|
|
p2.type = SPARK_TYPE_POINT;
|
|
p2.flag = SPARK_FLAG_STILL;
|
|
p2.x = px;
|
|
p2.y = py;
|
|
p2.z = pz;
|
|
|
|
SPARK_create(
|
|
&p1,
|
|
&p2,
|
|
20);
|
|
}
|
|
#endif
|
|
|
|
{
|
|
SLONG origin_x = p_person->WorldPos.X - SIN(p_person->Draw.Tweened->Angle) >> 8;
|
|
SLONG origin_z = p_person->WorldPos.Z - COS(p_person->Draw.Tweened->Angle) >> 8;
|
|
|
|
|
|
knock_person_down(
|
|
p_person,
|
|
30,
|
|
origin_x,
|
|
origin_z,
|
|
NULL);
|
|
|
|
// set_person_drop_down(p_person, 0); // 0 => Fall off backwards...
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_CLIMB_LANDING2:
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
set_person_on_fence(p_person);
|
|
}
|
|
break;
|
|
|
|
case SUB_STATE_CLIMB_AROUND_WALL:
|
|
break;
|
|
#ifdef UNUSED
|
|
case SUB_STATE_CLIMB_LEFT_WALL:
|
|
if(!check_limb_pos_on_fence_sideways(p_person, SUB_OBJECT_LEFT_HAND))
|
|
{
|
|
locked_anim_change(p_person,0,ANIM_CLIMB_UP_FENCE);
|
|
p_person->SubState=SUB_STATE_CLIMB_AROUND_WALL;
|
|
}
|
|
else
|
|
{
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
locked_anim_change(p_person,0,ANIM_CLIMB_UP_FENCE);
|
|
p_person->SubState=SUB_STATE_CLIMB_AROUND_WALL;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_CLIMB_RIGHT_WALL:
|
|
if(!check_limb_pos_on_fence_sideways(p_person, SUB_OBJECT_LEFT_HAND))
|
|
{
|
|
locked_anim_change(p_person,0,ANIM_CLIMB_UP_FENCE);
|
|
p_person->SubState=SUB_STATE_CLIMB_AROUND_WALL;
|
|
}
|
|
|
|
if(check_limb_pos_on_fence(p_person,SUB_OBJECT_HEAD)) //&&check_limb_pos_on_fence(p_person,SUB_OBJECT_RIGHT_HAND))
|
|
{
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
locked_anim_change(p_person,0,ANIM_CLIMB_UP_FENCE);
|
|
p_person->SubState=SUB_STATE_CLIMB_AROUND_WALL;
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
|
|
case SUB_STATE_CLIMB_UP_WALL:
|
|
|
|
//
|
|
// If our hand touches the top of a barbed-wire or angle-top fence, then
|
|
// fall off the fence.
|
|
//
|
|
|
|
if (dfacets[p_person->Genus.Person->OnFacet].FacetType == STOREY_TYPE_FENCE_BRICK ||
|
|
dfacets[p_person->Genus.Person->OnFacet].FacetType == STOREY_TYPE_FENCE)
|
|
{
|
|
if (!check_limb_pos_on_fence(p_person, SUB_OBJECT_RIGHT_HAND) ||
|
|
!check_limb_pos_on_fence(p_person, SUB_OBJECT_LEFT_HAND))
|
|
{
|
|
set_person_drop_down(p_person, 0);
|
|
|
|
goto dont_check_climbing_over;
|
|
}
|
|
}
|
|
|
|
if(check_limb_pos_on_fence(p_person,SUB_OBJECT_HEAD)) //&&check_limb_pos_on_fence(p_person,SUB_OBJECT_RIGHT_HAND))
|
|
{
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_HAND,ANIM_CLIMB_UP_FENCE);
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dfacets[p_person->Genus.Person->OnFacet].FacetType==STOREY_TYPE_NORMAL)
|
|
{
|
|
grab_ledge(p_person);
|
|
}
|
|
else
|
|
if (dfacets[p_person->Genus.Person->OnFacet].FacetType!=STOREY_TYPE_FENCE_BRICK)
|
|
{
|
|
//
|
|
// Climb off top of fence
|
|
//
|
|
p_person->SubState=SUB_STATE_CLIMB_OVER_WALL;
|
|
locked_anim_change(p_person,0,ANIM_CLIMB_OVER_FENCE);
|
|
set_limb_to_y(p_person,SUB_OBJECT_LEFT_HAND,get_fence_top(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,p_person->Genus.Person->OnFacet));
|
|
// p_person->Draw.Tweened->QueuedFrame=global_anim_array[p_person->Genus.Person->AnimType][ANIM_CLIMB_OVER_FENCE];
|
|
// p_person->Genus.Person->Action=ACTION_CLIMBING;
|
|
} // else blocked from climbing by barbed wire
|
|
}
|
|
/*
|
|
if(--p_person->Genus.Person->Timer1==0)
|
|
{
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
*/
|
|
|
|
dont_check_climbing_over:;
|
|
|
|
break;
|
|
|
|
case SUB_STATE_CLIMB_DOWN_WALL:
|
|
|
|
left_foot = check_limb_pos_on_fence(p_person,SUB_OBJECT_LEFT_FOOT);
|
|
right_foot = check_limb_pos_on_fence(p_person,SUB_OBJECT_RIGHT_FOOT);
|
|
|
|
if (left_foot && right_foot)
|
|
{
|
|
end = person_backwards_animate(p_person);
|
|
|
|
if (end == 1)
|
|
{
|
|
locked_anim_change_end(
|
|
p_person,
|
|
SUB_OBJECT_LEFT_HAND,
|
|
ANIM_CLIMB_UP_FENCE);//,p_person->Genus.Person->AnimType);
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The bottom of this fence might not be on the ground.
|
|
//
|
|
|
|
{
|
|
SLONG ground_y = PAP_calc_height_at_thing(
|
|
p_person,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
|
|
if ((p_person->WorldPos.Y >> 8) <= ground_y + 0x40)
|
|
{
|
|
//
|
|
// Climb off onto the ground.
|
|
//
|
|
|
|
p_person->SubState=SUB_STATE_CLIMB_OFF_BOT_WALL;
|
|
set_anim(p_person,ANIM_OFF_LADDER_BOT);
|
|
set_limb_to_y(p_person,SUB_OBJECT_RIGHT_FOOT,get_fence_bottom(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8,p_person->Genus.Person->OnFacet));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Fall off- this fence is in the air.
|
|
//
|
|
|
|
set_person_drop_down(p_person, 0); // 0 => Fall off backwards...
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
if(--p_person->Genus.Person->Timer1==0)
|
|
{
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
*/
|
|
|
|
break;
|
|
case SUB_STATE_CLIMB_OFF_BOT_WALL:
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
set_person_idle(p_person);
|
|
//set_anim(p_person,ANIM_OFF_LADDER_TOP);
|
|
p_person->Draw.Tweened->CurrentFrame=p_person->Draw.Tweened->QueuedFrame;
|
|
p_person->Draw.Tweened->NextFrame=p_person->Draw.Tweened->QueuedFrame;
|
|
p_person->Draw.Tweened->QueuedFrame=0;
|
|
plant_feet(p_person);
|
|
if(p_person->State!=STATE_DANGLING)
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_STAND_READY);
|
|
}
|
|
break;
|
|
case SUB_STATE_CLIMB_OVER_WALL:
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
// MSG_add(" drop down over fence \n");
|
|
set_person_locked_drop_down(p_person,-32);
|
|
p_person->WorldPos.Y+=p_person->DY;
|
|
// p_person->DY=-16;
|
|
//set_person_falling(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_STOPPING:
|
|
break;
|
|
default:
|
|
// ASSERT(0);
|
|
MSG_add("CLIMBING unknow substate %d \n",p_person->SubState);
|
|
break;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void set_cable_angle(Thing *p_person)
|
|
{
|
|
SLONG dx,dz;
|
|
struct DFacet *p_facet;
|
|
SLONG angle;
|
|
|
|
ASSERT(p_person->Genus.Person->Flags&FLAG_PERSON_ON_CABLE);
|
|
ASSERT(dfacets[p_person->Genus.Person->OnFacet].FacetType==STOREY_TYPE_CABLE);
|
|
|
|
p_facet=&dfacets[p_person->Genus.Person->OnFacet];
|
|
|
|
dx = p_facet->x[1] - p_facet->x[0] << 8;
|
|
dz = p_facet->z[1] - p_facet->z[0] << 8;
|
|
|
|
angle=calc_angle(dx,dz);
|
|
|
|
p_person->Draw.Tweened->Angle=angle;
|
|
}
|
|
|
|
|
|
|
|
void do_person_on_cable(Thing *p_person)
|
|
{
|
|
SLONG along;
|
|
SLONG mx,my,mz;
|
|
|
|
SLONG hx;
|
|
SLONG hy;
|
|
SLONG hz;
|
|
|
|
SLONG lhx,lhy,lhz;
|
|
SLONG rhx,rhy,rhz;
|
|
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_ON_CABLE)
|
|
{
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,SUB_OBJECT_LEFT_HAND,&lhx,&lhy,&lhz);
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,SUB_OBJECT_LEFT_HAND,&rhx,&rhy,&rhz);
|
|
|
|
hx = lhx + rhx >> 1;
|
|
hy = lhy + rhy >> 1;
|
|
hz = lhz + rhz >> 1;
|
|
|
|
along=get_cable_along(p_person->Genus.Person->OnFacet,(p_person->WorldPos.X>>8)+hx,(p_person->WorldPos.Z>>8)+hz);
|
|
|
|
my=find_cable_y_along(&dfacets[p_person->Genus.Person->OnFacet],along);
|
|
MSG_add(" death slide along %d my %d\n",along,my);
|
|
|
|
p_person->WorldPos.Y=(my-hy)<<8;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Why aren't we on a cable?
|
|
//
|
|
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
|
|
void fn_person_dangling(Thing *p_person)
|
|
{
|
|
SLONG ignore_building;
|
|
SLONG end;
|
|
SLONG hit;
|
|
SLONG grab;
|
|
SLONG wave_id1,
|
|
wave_id2;
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_STOPPING:
|
|
if(p_person->Genus.Person->OnFacet>0 && (p_person->Genus.Person->Flags&FLAG_PERSON_ON_CABLE) )
|
|
p_person->Genus.Person->Action=ACTION_DANGLING_CABLE;
|
|
|
|
break;
|
|
|
|
case SUB_STATE_GRAB_TO_DANGLE:
|
|
MSG_add("grab to dangle \n");
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
MSG_add("anim end \n");
|
|
p_person->Draw.Tweened->Locked=0;
|
|
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_ON_CABLE) //p_person->OnFace>0 && prim_faces4[p_person->OnFace].Type==FACE_TYPE_CABLE)
|
|
{
|
|
|
|
set_person_drop_down(p_person,PERSON_DROP_DOWN_OFF_FACE);
|
|
/*
|
|
|
|
p_person->SubState=SUB_STATE_DANGLING_CABLE;
|
|
MSG_add(" its a cable grab face %d",p_person->Genus.Person->OnFacet);
|
|
p_person->Draw.Tweened->Angle=find_best_cable_angle(p_person,p_person->Genus.Person->OnFacet);
|
|
|
|
p_person->Genus.Person->Action=ACTION_DANGLING_CABLE;
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_HAND,ANIM_HAND_OVER_HAND);
|
|
*/
|
|
|
|
}
|
|
else
|
|
|
|
|
|
{
|
|
p_person->SubState=SUB_STATE_DANGLING;
|
|
// MSG_add(" ledge dangle");
|
|
p_person->Genus.Person->Action=ACTION_DANGLING;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
}
|
|
//LogText(" set action dangling \n");
|
|
}
|
|
break;
|
|
case SUB_STATE_DEATH_SLIDE:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim==ANIM_DEATH_SLIDE)
|
|
{
|
|
set_anim(p_person,ANIM_WIRE_SLIDE_PULLUP);
|
|
}
|
|
else
|
|
if(p_person->Draw.Tweened->CurrentAnim==ANIM_WIRE_SLIDE_PULLUP)
|
|
{
|
|
set_anim(p_person,ANIM_WIRE_SLIDE_HANG);
|
|
}
|
|
|
|
}
|
|
p_person->Velocity+=p_person->DeltaVelocity;
|
|
if(p_person->Velocity>256)
|
|
p_person->Velocity=256;
|
|
person_death_slide(p_person);
|
|
break;
|
|
|
|
|
|
case SUB_STATE_DANGLING:
|
|
MSG_add(" dangling NORMAL ");
|
|
//LogText(" dangling action %d\n",p_person->Genus.Person->Action);
|
|
|
|
/*
|
|
|
|
if(Keys[KB_0])
|
|
set_person_idle(p_person);
|
|
|
|
*/
|
|
|
|
break;
|
|
case SUB_STATE_DANGLING_CABLE:
|
|
// MSG_add(" dangling cable ");
|
|
|
|
break;
|
|
case SUB_STATE_DANGLING_CABLE_FORWARD:
|
|
p_person->Draw.Tweened->Locked=0;
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
// MSG_add(" LOCKED CHANGE END FORWARD\n");
|
|
|
|
set_person_drop_down(p_person,PERSON_DROP_DOWN_OFF_FACE);
|
|
return;
|
|
// locked_anim_change(p_person,SUB_OBJECT_LEFT_HAND,ANIM_HAND_OVER_HAND);
|
|
}
|
|
do_person_on_cable(p_person);
|
|
|
|
break;
|
|
case SUB_STATE_DANGLING_CABLE_BACKWARD:
|
|
end=person_backwards_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
// MSG_add(" LOCKED CHANGE END \n");
|
|
set_person_drop_down(p_person,PERSON_DROP_DOWN_OFF_FACE);
|
|
return;
|
|
//locked_anim_change_end(p_person,SUB_OBJECT_LEFT_HAND,ANIM_HAND_OVER_HAND);
|
|
}
|
|
do_person_on_cable(p_person);
|
|
|
|
break;
|
|
|
|
|
|
case SUB_STATE_DROP_DOWN_OFF_FACE:
|
|
case SUB_STATE_DROP_DOWN:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end == 1)
|
|
{
|
|
if (p_person->Draw.Tweened->CurrentAnim == ANIM_PLUNGE_START)
|
|
{
|
|
locked_anim_change(p_person, SUB_OBJECT_PELVIS, ANIM_PLUNGE_FORWARDS);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Knock people over when you jump on them
|
|
//
|
|
|
|
drop_on_heads(p_person);
|
|
|
|
{
|
|
SLONG temp_angle;
|
|
|
|
//
|
|
// If you slip of a face then your velocity is not necessarily in the direction your facing
|
|
// (while slipping angleto is your movement angle), and it continues with dropdown
|
|
//
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_MOVE_ANGLETO)
|
|
{
|
|
temp_angle = p_person->Draw.Tweened->Angle;
|
|
p_person->Draw.Tweened->Angle = p_person->Draw.Tweened->AngleTo;
|
|
}
|
|
if(over_nogo(p_person))
|
|
p_person->Velocity=0;
|
|
|
|
if (p_person->DY<-4000)
|
|
{
|
|
if (p_person->Velocity>0)
|
|
{
|
|
hit=projectile_move_thing(p_person,3);
|
|
}
|
|
else
|
|
{
|
|
hit=projectile_move_thing(p_person,2|8|1); //2
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p_person->Velocity>0)
|
|
{
|
|
hit=projectile_move_thing(p_person,1);
|
|
}
|
|
else
|
|
{
|
|
hit=projectile_move_thing(p_person,1|8); //2
|
|
}
|
|
}
|
|
|
|
|
|
if(p_person->Genus.Person->Flags & FLAG_PERSON_MOVE_ANGLETO)
|
|
{
|
|
p_person->Draw.Tweened->Angle = temp_angle;
|
|
|
|
if(hit)
|
|
{
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_MOVE_ANGLETO;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hit == 100)
|
|
{
|
|
//
|
|
// Projectile move thing killed the person!
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
if (p_person->SubState == SUB_STATE_DROP_DOWN_OFF_FACE)
|
|
{
|
|
//
|
|
// We don't grab faces when falling (backwards) off a face.
|
|
//
|
|
|
|
grab = FALSE;
|
|
}
|
|
else
|
|
{
|
|
grab = grab_ledge(p_person);
|
|
}
|
|
|
|
if (!grab && hit == 1)
|
|
{
|
|
//
|
|
// projectile move thing sets person foot to floor height so need to
|
|
// maintain foot pos in world across anims
|
|
//
|
|
|
|
if (p_person->DY < -15000)
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_BIG_LAND);
|
|
}
|
|
else
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_LAND_VERT);
|
|
}
|
|
|
|
p_person->SubState = SUB_STATE_DROP_DOWN_LAND;
|
|
p_person->Genus.Person->Action = ACTION_LANDING;
|
|
|
|
person_splash(p_person, -1);
|
|
|
|
{
|
|
wave_id1 = footstep_wave(p_person);
|
|
wave_id2 = footstep_wave(p_person);
|
|
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id1,MFX_REPLACE,p_person);
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id2,MFX_REPLACE,p_person);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
case SUB_STATE_DROP_DOWN_OFF_FACE:
|
|
{
|
|
SLONG temp_angle;
|
|
|
|
|
|
//If you slip of a face then your velocity is not necessarily in the direction your facing
|
|
//(while slipping angleto is your movement angle), and it continues with dropdown
|
|
|
|
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_MOVE_ANGLETO)
|
|
{
|
|
temp_angle=p_person->Draw.Tweened->Angle;
|
|
p_person->Draw.Tweened->Angle=p_person->Draw.Tweened->AngleTo;
|
|
}
|
|
|
|
if(p_person->Velocity>0)
|
|
hit=projectile_move_thing(p_person,3);
|
|
else
|
|
hit=projectile_move_thing(p_person,2); //2
|
|
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_MOVE_ANGLETO)
|
|
{
|
|
p_person->Draw.Tweened->Angle=temp_angle;
|
|
if(hit)
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_MOVE_ANGLETO;
|
|
|
|
}
|
|
}
|
|
drop_on_heads(p_person);
|
|
if(hit==100)
|
|
{
|
|
//
|
|
// dead
|
|
//
|
|
|
|
return;
|
|
}
|
|
if(hit==1)
|
|
{
|
|
// MSG_add(" hit something while falling ");
|
|
if (p_person->DY < -15000)
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_BIG_LAND);
|
|
}
|
|
else
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_LAND_VERT);
|
|
|
|
}
|
|
//
|
|
// if (p_thing->DY < -5000)
|
|
// {
|
|
// queue_anim(p_person,ANIM_BIG_LAND);
|
|
// }
|
|
// else
|
|
// {
|
|
// queue_anim(p_person,ANIM_LAND_VERT);
|
|
//
|
|
// }
|
|
//
|
|
|
|
p_person->SubState = SUB_STATE_DROP_DOWN_LAND;
|
|
p_person->Genus.Person->Action = ACTION_LANDING;
|
|
|
|
person_splash(p_person, -1);
|
|
|
|
// if(p_person->Draw.Tweened->FrameIndex==1)
|
|
{
|
|
wave_id1 = footstep_wave(p_person);
|
|
wave_id2 = footstep_wave(p_person);
|
|
// play_quick_wave(p_person,wave_id1,WAVE_PLAY_INTERUPT);
|
|
// play_quick_wave(p_person,wave_id2,WAVE_PLAY_OVERLAP);
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id1,MFX_REPLACE,p_person);
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id2,MFX_REPLACE,p_person);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_DROP_DOWN:
|
|
|
|
// MSG_add(" Do DROP DOWN");
|
|
|
|
person_normal_animate(p_person);
|
|
|
|
{
|
|
SLONG temp_angle;
|
|
|
|
//
|
|
//If you slip of a face then your velocity is not necessarily in the direction your facing
|
|
//(while slipping angleto is your movement angle), and it continues with dropdown
|
|
//
|
|
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_MOVE_ANGLETO)
|
|
{
|
|
temp_angle=p_person->Draw.Tweened->Angle;
|
|
p_person->Draw.Tweened->Angle=p_person->Draw.Tweened->AngleTo;
|
|
}
|
|
|
|
if(p_person->Velocity>0)
|
|
hit=projectile_move_thing(p_person,3);
|
|
else
|
|
hit=projectile_move_thing(p_person,2);
|
|
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_MOVE_ANGLETO)
|
|
{
|
|
p_person->Draw.Tweened->Angle=temp_angle;
|
|
if(hit)
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_MOVE_ANGLETO;
|
|
|
|
}
|
|
}
|
|
drop_on_heads(p_person);
|
|
if(hit==100)
|
|
{
|
|
//
|
|
// dead
|
|
//
|
|
|
|
return;
|
|
}
|
|
//person_normal_move(p_person);
|
|
grab=grab_ledge(p_person);
|
|
if(grab)
|
|
MSG_add(" running jump grabbed \n");
|
|
if(!grab)
|
|
if(hit==1)
|
|
{
|
|
// MSG_add(" hit something while falling ");
|
|
// queue_anim(p_person,ANIM_LAND_VERT);
|
|
//
|
|
// projectile move thing sets person foot to floor height so need to maintain foot pos in world across anims
|
|
//
|
|
if (p_person->DY < -15000)
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_BIG_LAND);
|
|
}
|
|
else
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_LAND_VERT);
|
|
|
|
}
|
|
// plant_feet(p_person);
|
|
|
|
//DrawTween *draw_info;
|
|
//draw_info=p_person->Draw.Tweened;
|
|
//draw_info->QueuedFrame = global_anim_array[p_person->Genus.Person->AnimType][ANIM_LAND_VERT];
|
|
//draw_info->CurrentAnim = ANIM_LAND_VERT;
|
|
p_person->SubState = SUB_STATE_DROP_DOWN_LAND;
|
|
p_person->Genus.Person->Action = ACTION_LANDING;
|
|
|
|
person_splash(p_person, -1);
|
|
|
|
// if(p_person->Draw.Tweened->FrameIndex==1)
|
|
{
|
|
wave_id1 = footstep_wave(p_person);
|
|
wave_id2 = footstep_wave(p_person);
|
|
// play_quick_wave(p_person,wave_id1,WAVE_PLAY_INTERUPT);
|
|
// play_quick_wave(p_person,wave_id2,WAVE_PLAY_OVERLAP);
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id1,MFX_REPLACE,p_person);
|
|
MFX_play_thing(THING_NUMBER(p_person),wave_id2,MFX_REPLACE,p_person);
|
|
}
|
|
|
|
}
|
|
break;
|
|
*/
|
|
|
|
case SUB_STATE_DROP_DOWN_LAND:
|
|
change_velocity_to(p_person,0);
|
|
if(over_nogo(p_person))
|
|
p_person->Velocity=0;
|
|
person_normal_move(p_person);
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
set_person_idle(p_person);
|
|
if(p_person->SubState!=SUB_STATE_RUNNING)
|
|
plant_feet(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_TRAVERSE_LEFT:
|
|
case SUB_STATE_TRAVERSE_RIGHT:
|
|
end = person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
SLONG dist,dx,dz;
|
|
locked_anim_change(p_person,SUB_OBJECT_PELVIS,ANIM_DANGLE);
|
|
|
|
p_person->SubState = SUB_STATE_DANGLING;
|
|
p_person->Genus.Person->Action=ACTION_DANGLING;
|
|
/*
|
|
if((dist=abs(check_near_facet(p_person,64,64,(p_person->WorldPos.X)>>8,(p_person->WorldPos.Z)>>8)))==0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(abs(32-dist)<32)
|
|
{
|
|
SLONG angle;
|
|
angle=(p_person->Draw.Tweened->Angle+1024)&2047;
|
|
|
|
dx = -(SIN(angle) * (32-dist)) >> 8;
|
|
dz = -(COS(angle) * (32-dist)) >> 8;
|
|
|
|
}
|
|
|
|
person_normal_move_dxdz(p_person,dx,dz);
|
|
*/
|
|
#if 0
|
|
|
|
//
|
|
// How far is Darci from the facet she is hanging onto?
|
|
//
|
|
|
|
{
|
|
SLONG dist;
|
|
|
|
SLONG dx = -SIN(p_person->Draw.Tweened->Angle);
|
|
SLONG dz = -COS(p_person->Draw.Tweened->Angle);
|
|
|
|
if (abs(dx) > abs(dz))
|
|
{
|
|
if (dx > 0)
|
|
{
|
|
dist = 0x10000 - (p_person->WorldPos.X & 0xffff);
|
|
}
|
|
else
|
|
{
|
|
dist = p_person->WorldPos.X & 0xffff;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dz > 0)
|
|
{
|
|
dist = 0x10000 - (p_person->WorldPos.Z & 0xffff);
|
|
}
|
|
else
|
|
{
|
|
dist = p_person->WorldPos.Z & 0xffff;
|
|
}
|
|
}
|
|
#ifndef FINAL
|
|
PANEL_new_text(NULL, 4000, "Distance from facet = 0x%x", dist);
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_PULL_UP:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (MagicFrameCheck(p_person,2)) EffortSound(p_person);
|
|
|
|
if(end==1)
|
|
{
|
|
//
|
|
// Finished pulling ourselves up.
|
|
//
|
|
|
|
SLONG face,new_y;
|
|
//p_person->Draw.Tweened->Locked=0;
|
|
//p_person->SubState=SUB_STATE_DANGLING;
|
|
p_person->Draw.Tweened->AnimTween=0;
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_STAND_READY);
|
|
|
|
if (p_person->Flags & FLAGS_IN_BUILDING)
|
|
{
|
|
ignore_building = INDOORS_DBUILDING;
|
|
}
|
|
else
|
|
{
|
|
ignore_building = NULL;
|
|
}
|
|
|
|
//
|
|
// Find what face we are stood on now
|
|
//
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
if (p_person->Flags & FLAGS_IN_SEWERS)
|
|
{
|
|
p_person->OnFace = 0;
|
|
p_person->WorldPos.Y = NS_calc_height_at(p_person->WorldPos.X >> 8, p_person->WorldPos.Z >> 8) << 8;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
face = find_face_for_this_pos(p_person->WorldPos.X>>8,p_person->WorldPos.Y>>8,p_person->WorldPos.Z>>8,&new_y,ignore_building,0);
|
|
|
|
if(face==GRAB_FLOOR)
|
|
{
|
|
ASSERT(0);
|
|
|
|
p_person->OnFace=0;
|
|
p_person->WorldPos.Y=new_y<<8;
|
|
}
|
|
else
|
|
if(face)
|
|
{
|
|
p_person->OnFace=face;
|
|
// new_y=calc_height_on_face(p_person->WorldPos.X,p_person->WorldPos.Z,face);
|
|
p_person->WorldPos.Y=new_y<<8;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0);
|
|
|
|
p_person->WorldPos.Y=0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// This is a subset of set person idle (the set anim stuff is removed
|
|
//
|
|
|
|
set_person_idle(p_person);
|
|
|
|
/*
|
|
set_generic_person_state_function(p_person,STATE_IDLE);
|
|
p_person->SubState=0;
|
|
p_person->Genus.Person->Action=ACTION_IDLE;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
*/
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
set_person_drop_down(p_person, 0); // EMERGENCY!
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
extern void trickle_velocity_to(Thing *p_thing,SWORD velocity);
|
|
|
|
|
|
void set_person_running_stop(Thing *p_person,SLONG leg)
|
|
{
|
|
|
|
// tween_to_anim(p_person,ANIM_STOP_RUN_L+leg);
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
|
|
WaveParams foot_step;
|
|
|
|
|
|
SLONG should_person_automatically_land_on_fence(Thing *p_person, SLONG facet)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG da;
|
|
SLONG mdx;
|
|
SLONG mdz;
|
|
SLONG angle;
|
|
|
|
DFacet *df;
|
|
|
|
df = &dfacets[facet];
|
|
|
|
//
|
|
// Only players...
|
|
//
|
|
|
|
if (p_person->Genus.Person->PlayerID == 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
if (p_special->Genus.Special->SpecialType == SPECIAL_WIRE_CUTTER)
|
|
{
|
|
//
|
|
// While holding wire cutters don't auto climb fences, because you might want to cut it
|
|
//
|
|
return(FALSE);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Is this a climbable fence facet?
|
|
//
|
|
|
|
if (df->FacetType == STOREY_TYPE_FENCE ||
|
|
df->FacetType == STOREY_TYPE_NORMAL ||
|
|
df->FacetType == STOREY_TYPE_FENCE_FLAT ||
|
|
df->FacetType == STOREY_TYPE_FENCE_BRICK)
|
|
{
|
|
if (!(df->FacetFlags & FACET_FLAG_UNCLIMBABLE))
|
|
{
|
|
//
|
|
// Is the person's angle correct?
|
|
//
|
|
|
|
dx = abs(df->x[1] - df->x[0] << 8);
|
|
dz = abs(df->z[1] - df->z[0] << 8);
|
|
|
|
angle = Arctan(-dx,dz) + 1536;
|
|
angle &= 2047;
|
|
|
|
da = abs(angle - p_person->Draw.Tweened->Angle);
|
|
|
|
#define FENCE_DA 128
|
|
|
|
if ((da > FENCE_DA && da < 1024 - FENCE_DA ) ||
|
|
(da > FENCE_DA + 1024 && da < 2048 - FENCE_DA ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
|
|
if (da > 512 && da < 2048 - 512)
|
|
{
|
|
angle += 1024;
|
|
angle &= 2047;
|
|
}
|
|
|
|
*/
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void process_a_vaulting_person(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if(p_person->Draw.Tweened->FrameIndex==6)
|
|
{
|
|
SLONG wx,wy,wz,fy;
|
|
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,SUB_OBJECT_LEFT_FOOT,&wx,&wy,&wz);
|
|
|
|
wx += p_person->WorldPos.X >> 8;
|
|
wy += p_person->WorldPos.Y >> 8;
|
|
wz += p_person->WorldPos.Z >> 8;
|
|
|
|
fy=PAP_calc_height_at(wx,wz);
|
|
|
|
if(abs(fy-(wy-12))>8)
|
|
{
|
|
p_person->Velocity = 6;
|
|
p_person->DY = -(10 << 8);
|
|
set_person_drop_down(p_person,PERSON_DROP_DOWN_KEEP_VEL|PERSON_DROP_DOWN_KEEP_DY);//|PERSON_DROP_DOWN_OFF_FACE);
|
|
}
|
|
}
|
|
|
|
if(end==1)
|
|
{
|
|
p_person->Genus.Person->Flags &= ~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
locked_anim_change(p_person,0,ANIM_STAND_READY);
|
|
|
|
//
|
|
// Only non-player characters can continue running.
|
|
//
|
|
|
|
if (p_person->Genus.Person->PlayerID && continue_moveing(p_person))
|
|
{
|
|
set_person_running(p_person);
|
|
}
|
|
else
|
|
{
|
|
set_person_idle(p_person);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void set_person_sit_down(Thing *p_person)
|
|
{
|
|
set_generic_person_state_function(p_person, STATE_MOVEING);
|
|
|
|
set_person_do_a_simple_anim(p_person, ANIM_SIT_DOWN);
|
|
|
|
p_person->SubState = SUB_STATE_SIMPLE_ANIM;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NO_RETURN_TO_NORMAL;
|
|
p_person->Genus.Person->Action = ACTION_SIT_BENCH;
|
|
|
|
if (GAME_FLAGS & GF_DISABLE_BENCH_HEALTH)
|
|
{
|
|
p_person->Genus.Person->Timer1 = 100;
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
GAME_FLAGS |= GF_DISABLE_BENCH_HEALTH;
|
|
}
|
|
}
|
|
|
|
void set_person_unsit(Thing *p_person)
|
|
{
|
|
set_generic_person_state_function(p_person, STATE_MOVEING);
|
|
|
|
set_person_do_a_simple_anim(p_person, ANIM_SIT_TO_STAND);
|
|
|
|
p_person->SubState = SUB_STATE_SIMPLE_ANIM;
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_NO_RETURN_TO_NORMAL;
|
|
p_person->Genus.Person->Action = ACTION_UNSIT;
|
|
}
|
|
|
|
|
|
SLONG person_holding_2handed(Thing *p_person)
|
|
{
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
//
|
|
// The shotgun and ak47 have their own special shotgun yomp.
|
|
//
|
|
|
|
if (p_special->Genus.Special->SpecialType == SPECIAL_SHOTGUN ||
|
|
// p_special->Genus.Special->SpecialType == SPECIAL_BASEBALLBAT ||
|
|
p_special->Genus.Special->SpecialType == SPECIAL_AK47)
|
|
{
|
|
return(1);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
SLONG person_holding_special(Thing* p_person, UBYTE special)
|
|
{
|
|
if (!p_person->Genus.Person->SpecialUse) return 0;
|
|
|
|
Thing* p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
return (p_special->Genus.Special->SpecialType == special) ? 1 : 0;
|
|
}
|
|
|
|
SLONG get_yomp_anim(Thing *p_person)
|
|
{
|
|
|
|
|
|
if(p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
return(ANIM_PISTOL_JOG);
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
//
|
|
// The shotgun and ak47 have their own special shotgun yomp.
|
|
//
|
|
|
|
if (p_special->Genus.Special->SpecialType == SPECIAL_BASEBALLBAT)
|
|
{
|
|
return(ANIM_YOMP_BAT);
|
|
}
|
|
|
|
if (p_special->Genus.Special->SpecialType == SPECIAL_SHOTGUN ||
|
|
p_special->Genus.Special->SpecialType == SPECIAL_AK47)
|
|
{
|
|
return(ANIM_AK_JOG);
|
|
}
|
|
}
|
|
if(p_person->Genus.Person->PersonType==PERSON_COP)
|
|
{
|
|
return(COP_ROPER_ANIM_RUN);
|
|
}
|
|
else
|
|
return(ANIM_YOMP);
|
|
}
|
|
|
|
void fn_person_moveing(Thing *p_person)
|
|
{
|
|
UBYTE last_frame;
|
|
SLONG end,
|
|
foot_step_wave;
|
|
SLONG yomp,sprint,change,stamina_used;
|
|
|
|
MSG_add(" state %d substate %d vel %d \n",p_person->State,p_person->SubState,p_person->Velocity);
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
camera_normal();
|
|
}
|
|
|
|
//LogText(" person moveing substate %d\n",p_person->SubState);
|
|
|
|
//return;
|
|
if (p_person->SubState == SUB_STATE_RUNNING ||
|
|
p_person->SubState == SUB_STATE_WALKING )
|
|
{
|
|
//
|
|
//
|
|
//
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_STAND_HIP:
|
|
case ANIM_STAND_READY:
|
|
case ANIM_SHOTGUN_IDLE:
|
|
case COP_ROPER_ANIM_READY:
|
|
case ANIM_FIGHT:
|
|
{
|
|
SLONG anim;
|
|
anim=get_yomp_anim(p_person);
|
|
if(anim==COP_ROPER_ANIM_RUN)
|
|
{
|
|
set_anim_of_type(p_person,anim,ANIM_TYPE_ROPER);
|
|
}
|
|
else
|
|
set_anim(p_person,anim);
|
|
}
|
|
break;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
if (p_person->SubState == SUB_STATE_RUNNING ||
|
|
p_person->SubState == SUB_STATE_WALKING ||
|
|
p_person->SubState == SUB_STATE_SNEAKING ||
|
|
p_person->SubState == SUB_STATE_RUNNING_SKID_STOP ||
|
|
p_person->SubState == SUB_STATE_RUNNING_THEN_JUMP)
|
|
{
|
|
if (p_person->Draw.Tweened->FrameIndex == 1)
|
|
{
|
|
person_splash(p_person, SUB_OBJECT_RIGHT_FOOT);
|
|
}
|
|
else
|
|
if (p_person->Draw.Tweened->FrameIndex == 5)
|
|
{
|
|
person_splash(p_person, SUB_OBJECT_LEFT_FOOT);
|
|
}
|
|
}
|
|
SlideSoundCheck(p_person);
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_ENTERING_VEHICLE:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
set_person_in_vehicle(p_person,TO_THING(p_person->Genus.Person->InCar));
|
|
}
|
|
break;
|
|
|
|
case SUB_STATE_INSIDE_VEHICLE:
|
|
|
|
//
|
|
// We are not on the mapwho at this point- so we just track the position of
|
|
// the vehicle we are in and teleport to that place.
|
|
//
|
|
|
|
p_person->WorldPos = TO_THING(p_person->Genus.Person->InCar)->WorldPos;
|
|
p_person->Draw.Tweened->Angle = TO_THING(p_person->Genus.Person->InCar)->Genus.Vehicle->Angle;
|
|
|
|
//
|
|
// Vehicles can drive off the map!
|
|
//
|
|
|
|
SATURATE(p_person->WorldPos.X, 0, (PAP_SIZE_HI << 16) - 1);
|
|
SATURATE(p_person->WorldPos.Z, 0, (PAP_SIZE_HI << 16) - 1);
|
|
|
|
break;
|
|
|
|
case SUB_STATE_EXITING_VEHICLE:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
set_person_out_of_vehicle(p_person);
|
|
}
|
|
break;
|
|
|
|
case SUB_STATE_SLIPPING_END:
|
|
change_velocity_to(p_person,0);
|
|
if(p_person->Velocity==0)
|
|
{
|
|
set_person_idle(p_person);
|
|
return;
|
|
}
|
|
|
|
case SUB_STATE_SLIPPING:
|
|
{
|
|
SLONG angle;
|
|
angle=p_person->Draw.Tweened->Angle;
|
|
p_person->Draw.Tweened->Angle=p_person->Draw.Tweened->AngleTo;
|
|
|
|
person_normal_move(p_person);
|
|
|
|
p_person->Draw.Tweened->Angle=angle;
|
|
|
|
}
|
|
|
|
{
|
|
SLONG fx,fy,fz,px,pz,rgb,sz,i,j;
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_LEFT_FOOT, &fx, &fy, &fz);
|
|
fx=(fx<<8) + p_person->WorldPos.X;
|
|
fy=(fy<<8) + p_person->WorldPos.Y;
|
|
fz=(fz<<8) + p_person->WorldPos.Z;
|
|
// rgb=0xFF-(p_person->Velocity<<2);
|
|
rgb=0x7F-(p_person->Velocity<<1);
|
|
if (rgb<0)
|
|
{
|
|
rgb=0;
|
|
}
|
|
rgb=(rgb<<24)|0xc9b7a3;
|
|
j=(p_person->Velocity>40) ? 7 : 3;
|
|
for (i=0;i<j;i++)
|
|
{
|
|
px=fx+(((Random()&0x7ff)-0x3ff)<<2);
|
|
pz=fz+(((Random()&0x7ff)-0x3ff)<<2);
|
|
PARTICLE_Add(px,fy,pz,(Random()&7)-3,20,(Random()&7)-3,POLY_PAGE_SMOKECLOUD2,2+((Random()&3)<<2),rgb,PFLAG_FADE|PFLAG_RESIZE,40,25,1,10,4);
|
|
}
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
break;
|
|
|
|
case SUB_STATE_RUNNING_HALF_BLOCK:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
locked_anim_change(p_person,0,ANIM_STAND_READY);
|
|
plant_feet(p_person);
|
|
if(p_person->State!=STATE_DANGLING)
|
|
set_person_idle(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_RUNNING_VAULT:
|
|
process_a_vaulting_person(p_person);
|
|
break;
|
|
|
|
case SUB_STATE_RUNNING_HIT_WALL:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
set_person_idle(p_person);
|
|
|
|
//set_person_turn_to_hug_wall(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_RUNNING:
|
|
//LogText(" running \n");
|
|
|
|
last_frame = p_person->Draw.Tweened->FrameIndex;
|
|
last_slide_colvect=0;
|
|
|
|
// p_person->Flags&=~FLAG_PERSON_AIM_AND_RUN;
|
|
if(!(p_person->Genus.Person->Flags2&FLAG2_PERSON_CARRYING))
|
|
if(p_person->Genus.Person->PlayerID)// && p_person->Draw.Tweened->CurrentAnim==ANIM_YOMP)
|
|
{
|
|
if (p_person->Genus.Person->Timer1)
|
|
{
|
|
SLONG ticks = 16 * TICK_RATIO >> TICK_SHIFT;
|
|
|
|
//
|
|
// Countdown since te person last fired his gun.
|
|
//
|
|
|
|
if (p_person->Genus.Person->Timer1 <= ticks)
|
|
{
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
if (p_special->Genus.Special->SpecialType == SPECIAL_AK47)
|
|
{
|
|
if (continue_firing(p_person))
|
|
{
|
|
set_person_running_shoot(p_person);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Timer1 -= ticks;
|
|
}
|
|
}
|
|
|
|
//if(p_person->Draw.Tweened->CurrentAnim==ANIM_AK_JOG)
|
|
if(person_has_gun_out(p_person))
|
|
{
|
|
//
|
|
// we are jogging along with a shotgun or ak47 or pistol lets aim at people
|
|
//
|
|
|
|
player_running_aim_gun(p_person);
|
|
|
|
}
|
|
|
|
}
|
|
end=person_normal_animate(p_person);
|
|
|
|
p_person->DY=0;
|
|
|
|
|
|
if(end==1)
|
|
{
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_HIT_WALL:
|
|
case ANIM_YOMP_START:
|
|
case ANIM_YOMP_START_PISTOL:
|
|
case ANIM_YOMP_START_AK:
|
|
case ANIM_YOMP_START_BAT:
|
|
|
|
{
|
|
UWORD anim;
|
|
|
|
anim=get_yomp_anim(p_person);
|
|
if(anim==COP_ROPER_ANIM_RUN)
|
|
{
|
|
set_anim_of_type(p_person,anim,ANIM_TYPE_ROPER);
|
|
}
|
|
else
|
|
set_anim(p_person,anim);
|
|
}
|
|
|
|
break;
|
|
case ANIM_START_WALK_CARRY:
|
|
{
|
|
Thing *p_target;
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
set_anim(p_target,ANIM_WALK_CARRY_V);
|
|
set_anim(p_person,ANIM_WALK_CARRY);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
switch(p_person->Genus.Person->AnimType)
|
|
{
|
|
case ANIM_TYPE_ROPER:
|
|
sprint=60;
|
|
yomp=34;
|
|
// change=15;
|
|
change=40; // immediately :}
|
|
// stamina_used=1;
|
|
stamina_used=4; // since roper runs all the time...
|
|
break;
|
|
default: // darci, others
|
|
sprint=sprint_speed;
|
|
yomp=yomp_speed;
|
|
change=50;
|
|
stamina_used=2;
|
|
break;
|
|
}
|
|
*/
|
|
|
|
sprint=sprint_speed;
|
|
yomp=yomp_speed;
|
|
change=50;
|
|
stamina_used = ((PTIME(p_person) & 0x3) == 0);
|
|
|
|
if(p_person->Genus.Person->AnimType==ANIM_TYPE_ROPER)
|
|
{
|
|
stamina_used=4;
|
|
|
|
}
|
|
|
|
{
|
|
SLONG run_speed=yomp; //_speed;
|
|
if(p_person->Genus.Person->Mode==PERSON_MODE_SPRINT)
|
|
{
|
|
run_speed=sprint; //_speed;
|
|
|
|
if (p_person->Genus.Person->Stamina < 10)
|
|
{
|
|
p_person->Genus.Person->Stamina=0;
|
|
p_person->Genus.Person->Mode=PERSON_MODE_RUN;
|
|
switch(p_person->Genus.Person->PersonType) {
|
|
case PERSON_DARCI:
|
|
MFX_play_thing(THING_NUMBER(p_person),S_DARCI_OUTOFBREATH,MFX_MOVING,p_person);
|
|
break;
|
|
case PERSON_ROPER:
|
|
MFX_play_thing(THING_NUMBER(p_person),S_ROPER_OUTOFBREATH,MFX_MOVING,p_person);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Stamina-=stamina_used;
|
|
}
|
|
|
|
if(p_person->Draw.Tweened->CurrentAnim == ANIM_YOMP)
|
|
{
|
|
if(end||(change==1))
|
|
if(p_person->Velocity>change)
|
|
set_anim(p_person,ANIM_RUN);
|
|
}
|
|
|
|
//
|
|
// accelerate twice in sprint mode
|
|
//
|
|
|
|
change_velocity_to(p_person,run_speed);
|
|
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim == ANIM_RUN)
|
|
{
|
|
if(end)
|
|
if(p_person->Velocity<change-5)
|
|
set_anim(p_person,ANIM_YOMP);
|
|
}
|
|
}
|
|
|
|
change_velocity_to(p_person,run_speed);
|
|
extern UBYTE cheat;
|
|
// if(cheat==1)
|
|
// change_velocity_to(p_person,run_speed*2);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(p_person->Draw.Tweened->CurrentAnim==ANIM_YOMP_START || p_person->Draw.Tweened->CurrentAnim==ANIM_YOMP_START_AK|| p_person->Draw.Tweened->CurrentAnim==ANIM_YOMP_START_PISTOL|| p_person->Draw.Tweened->CurrentAnim==ANIM_YOMP_START_BAT)
|
|
{
|
|
if(p_person->Draw.Tweened->FrameIndex<2)
|
|
p_person->Velocity=0;
|
|
}
|
|
|
|
last_slide_colvect=0;
|
|
person_normal_move(p_person);
|
|
|
|
//SLONG along_middle_of_facet(Thing *p_person,SLONG col)
|
|
if(p_person->Genus.Person->Flags2&FLAG2_PERSON_CARRYING)
|
|
{
|
|
carry_running(p_person);
|
|
}
|
|
else
|
|
{
|
|
if(last_slide_colvect&&along_middle_of_facet(p_person,last_slide_colvect))
|
|
{
|
|
// p_person->Velocity>>=1;
|
|
if (is_facet_vaultable(last_slide_colvect))
|
|
{
|
|
if(set_person_vault(p_person,last_slide_colvect))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
if (is_facet_half_step(last_slide_colvect))
|
|
{
|
|
if(set_person_climb_half(p_person,last_slide_colvect))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (should_person_automatically_land_on_fence(p_person,last_slide_colvect))
|
|
{
|
|
set_person_land_on_fence(p_person, last_slide_colvect, 1,1);
|
|
return;
|
|
}
|
|
|
|
//#define WE_WANT_TO_TURN_AND_PUT_OUR_BACK_TO_THE_WALL 77179
|
|
#ifdef WE_WANT_TO_TURN_AND_PUT_OUR_BACK_TO_THE_WALL
|
|
|
|
if(p_person->Velocity>35)
|
|
{
|
|
SLONG wall_angle;
|
|
if(is_wall_good_for_bump_and_turn(p_person,last_slide_colvect))
|
|
if(am_i_facing_wall(p_person,last_slide_colvect,&wall_angle))
|
|
{
|
|
p_person->Velocity=0;
|
|
ASSERT((wall_angle&0x1ff)==0);
|
|
p_person->Draw.Tweened->Angle=(wall_angle)&2047;
|
|
set_person_turn_to_hug_wall(p_person);
|
|
|
|
// set_person_idle(p_person);
|
|
// set_anim(p_person,ANIM_HIT_WALL);
|
|
// p_person->SubState=SUB_STATE_RUNNING_HIT_WALL;
|
|
return;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
if(0)
|
|
if(p_person->Velocity>35)
|
|
{
|
|
SLONG wall_angle;
|
|
if(is_wall_good_for_bump_and_turn(p_person,last_slide_colvect))
|
|
if(am_i_facing_wall(p_person,last_slide_colvect,&wall_angle))
|
|
{
|
|
p_person->Velocity=0;
|
|
ASSERT((wall_angle&0x1ff)==0);
|
|
p_person->Draw.Tweened->Angle=(wall_angle)&2047;
|
|
|
|
// set_person_idle(p_person);
|
|
set_anim(p_person,ANIM_HIT_WALL);
|
|
p_person->SubState=SUB_STATE_RUNNING_HIT_WALL;
|
|
if(p_person->Genus.Person->PersonType==PERSON_DARCI)
|
|
MFX_play_thing(THING_NUMBER(p_person),SOUND_Range(S_DARCI_EFFORT_START,S_DARCI_EFFORT_END),0,p_person);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
if(slide_ladder)
|
|
{
|
|
if(mount_ladder(p_person, slide_ladder))
|
|
return;
|
|
|
|
|
|
}
|
|
}
|
|
// if(p_person->Draw.Tweened->FrameIndex==0 || p_person->Draw.Tweened->FrameIndex==3)
|
|
// if(p_person->Draw.Tweened->FrameIndex==1 || p_person->Draw.Tweened->FrameIndex==5)
|
|
if(p_person->Draw.Tweened->FrameIndex==1 || p_person->Draw.Tweened->FrameIndex==(4+(p_person->Genus.Person->Mode==PERSON_MODE_RUN)))
|
|
{
|
|
if (p_person->Flags & FLAGS_PLAYED_FOOTSTEP)
|
|
{
|
|
//
|
|
// Don't play twice!
|
|
//
|
|
}
|
|
else
|
|
{
|
|
foot_step_wave = footstep_wave(p_person);
|
|
|
|
/*
|
|
|
|
oscilate_tinpanum(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
p_person,
|
|
64);
|
|
|
|
*/
|
|
|
|
PCOM_oscillate_tympanum(
|
|
PCOM_SOUND_FOOTSTEP,
|
|
p_person,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
|
|
foot_step.Flags = WAVE_CARTESIAN;
|
|
foot_step.Priority = 0;
|
|
foot_step.Mode.Cartesian.Scale = (128<<8);
|
|
foot_step.Mode.Cartesian.X = p_person->WorldPos.X;
|
|
foot_step.Mode.Cartesian.Y = p_person->WorldPos.Y;
|
|
foot_step.Mode.Cartesian.Z = p_person->WorldPos.Z;
|
|
|
|
/*
|
|
if(GAME_FLAGS&GF_SEWERS && p_person->Draw.Tweened->FrameIndex!=last_frame)
|
|
{
|
|
foot_step_wave = ((Random()*(S_FOOTS_SEWER_END-S_FOOTS_SEWER_START))>>16)+S_FOOTS_SEWER_START;;
|
|
// PlayWave(THING_NUMBER(p_person),foot_step_wave,WAVE_PLAY_OVERLAP,&foot_step);
|
|
play_quick_wave_old(&foot_step,foot_step_wave,0,0);
|
|
}
|
|
else
|
|
{
|
|
// PlayWave(THING_NUMBER(p_person),foot_step_wave,WAVE_PLAY_INTERUPT,&foot_step);
|
|
play_quick_wave_old(&foot_step,foot_step_wave,0,0);
|
|
}
|
|
*/
|
|
// play_quick_wave_old(&foot_step,foot_step_wave,0,0);
|
|
MFX_play_thing(THING_NUMBER(p_person),foot_step_wave,MFX_REPLACE,p_person);
|
|
|
|
p_person->Flags |= FLAGS_PLAYED_FOOTSTEP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p_person->Flags &= ~FLAGS_PLAYED_FOOTSTEP;
|
|
}
|
|
|
|
|
|
|
|
// MSG_add(" velocity %d \n",p_person->Velocity);
|
|
|
|
break;
|
|
case SUB_STATE_CRAWLING:
|
|
if(slope_ahead(p_person,100))
|
|
return;
|
|
|
|
/*
|
|
switch(p_person->Genus.Person->AnimType)
|
|
{
|
|
// case ANIM_TYPE_ROPER:
|
|
// change_velocity_to(p_person,7);
|
|
// break;
|
|
default: // darci, others
|
|
*/
|
|
change_velocity_to(p_person,15);
|
|
/*
|
|
break;
|
|
}
|
|
*/
|
|
person_normal_move(p_person);
|
|
person_normal_animate(p_person);
|
|
break;
|
|
case SUB_STATE_WALKING:
|
|
|
|
if(p_person->Genus.Person->PersonType==PERSON_CIV)
|
|
{
|
|
SLONG old;
|
|
if(!(p_person->Draw.Tweened->MeshID&1))
|
|
change_velocity_to(p_person,14);
|
|
else
|
|
change_velocity_to(p_person,10); //bloody women, walking round slow
|
|
}
|
|
else
|
|
change_velocity_to(p_person,16);
|
|
person_normal_move(p_person);
|
|
|
|
//
|
|
// Make walking people able to vault fences too.
|
|
//
|
|
|
|
if(last_slide_colvect && is_facet_vaultable(last_slide_colvect))
|
|
{
|
|
set_person_vault(p_person,last_slide_colvect);
|
|
return;
|
|
|
|
}
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
if(slide_ladder)
|
|
{
|
|
if(mount_ladder(p_person, slide_ladder))
|
|
return;
|
|
}
|
|
|
|
person_normal_animate(p_person);
|
|
if(p_person->Draw.Tweened->FrameIndex==1 || p_person->Draw.Tweened->FrameIndex==5)
|
|
{
|
|
if (p_person->Flags & FLAGS_PLAYED_FOOTSTEP)
|
|
{
|
|
//
|
|
// Don't play twice!
|
|
//
|
|
}
|
|
else
|
|
{
|
|
foot_step_wave = footstep_wave(p_person);
|
|
|
|
/* //nah were only walking
|
|
PCOM_oscillate_tympanum(
|
|
PCOM_SOUND_FOOTSTEP,
|
|
p_person,
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
*/
|
|
|
|
foot_step.Flags = WAVE_CARTESIAN;
|
|
foot_step.Priority = 0;
|
|
foot_step.Mode.Cartesian.Scale = (128<<8);
|
|
foot_step.Mode.Cartesian.X = p_person->WorldPos.X;
|
|
foot_step.Mode.Cartesian.Y = p_person->WorldPos.Y;
|
|
foot_step.Mode.Cartesian.Z = p_person->WorldPos.Z;
|
|
|
|
MFX_play_thing(THING_NUMBER(p_person),foot_step_wave,MFX_REPLACE,p_person);
|
|
|
|
p_person->Flags |= FLAGS_PLAYED_FOOTSTEP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p_person->Flags &= ~FLAGS_PLAYED_FOOTSTEP;
|
|
}
|
|
|
|
|
|
break;
|
|
case SUB_STATE_WALKING_BACKWARDS:
|
|
change_velocity_to(p_person,-16);
|
|
person_normal_move(p_person);
|
|
person_normal_animate(p_person);
|
|
//person_backwards_animate(p_person);
|
|
break;
|
|
/*
|
|
case SUB_STATE_SNEAKING:
|
|
change_velocity_to(p_person,16);
|
|
person_normal_move(p_person);
|
|
person_normal_animate(p_person);
|
|
break;
|
|
*/
|
|
case SUB_STATE_RUN_STOP:
|
|
person_normal_move(p_person);
|
|
end=person_normal_animate(p_person);
|
|
change_velocity_to(p_person,0);
|
|
|
|
if(end)
|
|
{
|
|
p_person->SubState=SUB_STATE_STOPPING;
|
|
}
|
|
break;
|
|
case SUB_STATE_RUNNING_SKID_STOP:
|
|
person_normal_move(p_person);
|
|
if(check_on_slippy_slope(p_person))
|
|
return;
|
|
if(slope_ahead(p_person,50))
|
|
{
|
|
return;
|
|
|
|
}
|
|
|
|
end=person_normal_animate(p_person);
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_SLIDER_START:
|
|
if(p_person->Velocity>42)
|
|
p_person->Velocity=42;
|
|
// change_velocity_to_slow(p_person,40);
|
|
if(end)
|
|
{
|
|
set_anim(p_person,ANIM_SLIDER_HOLD);
|
|
}
|
|
break;
|
|
case ANIM_SLIDER_HOLD:
|
|
|
|
{
|
|
SLONG fx,fy,fz,px,pz,rgb,sz,i,j;
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_LEFT_FOOT, &fx, &fy, &fz);
|
|
fx=(fx<<8) + p_person->WorldPos.X;
|
|
fy=(fy<<8) + p_person->WorldPos.Y;
|
|
fz=(fz<<8) + p_person->WorldPos.Z;
|
|
#ifdef PSX
|
|
rgb=0x20505050;
|
|
#else
|
|
rgb=0xFF-(p_person->Velocity<<2);
|
|
if (rgb<0) rgb=0;
|
|
rgb=(rgb<<24)|0xc9b7a3;
|
|
j=(p_person->Velocity>40) ? 7 : 3;
|
|
for (i=0;i<j;i++)
|
|
#endif
|
|
{
|
|
px=fx+(((Random()&0x7ff)-0x3ff)<<2);
|
|
pz=fz+(((Random()&0x7ff)-0x3ff)<<2);
|
|
PARTICLE_Add(px,fy,pz,(Random()&7)-3,20,(Random()&7)-3,POLY_PAGE_SMOKECLOUD2,2+((Random()&3)<<2),rgb,PFLAG_FADE|PFLAG_RESIZE|PFLAG_SPRITEANI|PFLAG_SPRITELOOP,40,25,1,10,4);
|
|
|
|
}
|
|
}
|
|
change_velocity_to_slow(p_person,0);
|
|
if(p_person->Velocity<25)
|
|
{
|
|
set_anim(p_person,ANIM_SLIDER_END);
|
|
}
|
|
break;
|
|
case ANIM_SLIDER_END:
|
|
MFX_stop(THING_NUMBER(p_person),S_SLIDE_START);
|
|
if (p_person->Velocity>5)
|
|
{
|
|
SLONG px,py,pz,rgb,sz;
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_LEFT_FOOT, &px, &py, &pz);
|
|
px=(px<<8) + p_person->WorldPos.X;
|
|
py=(py<<8) + p_person->WorldPos.Y;
|
|
pz=(pz<<8) + p_person->WorldPos.Z;
|
|
#ifdef PSX
|
|
rgb=0x20505050;
|
|
#else
|
|
rgb=0xFF-(p_person->Velocity<<2);
|
|
if (rgb<0) rgb=0;
|
|
rgb=(rgb<<24)|0xc9b7a3;
|
|
#endif
|
|
PARTICLE_Add(px,py,pz,(Random()&7)-3,20,(Random()&7)-3,POLY_PAGE_SMOKECLOUD2,2+((Random()&3)<<2),rgb,PFLAG_FADE|PFLAG_RESIZE|PFLAG_SPRITEANI|PFLAG_SPRITELOOP,40,25,1,10,4);
|
|
}
|
|
change_velocity_to(p_person,0);
|
|
if(end)
|
|
{
|
|
set_person_locked_idle_ready(p_person);
|
|
p_person->Velocity=1;
|
|
|
|
person_normal_move(p_person);
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Put some leeway in the jump frames so she jumps
|
|
// more responsively.
|
|
//
|
|
/*
|
|
if (WITHIN(p_person->Draw.Tweened->FrameIndex, 0, 0))
|
|
{
|
|
set_person_running_stop(p_person,0);
|
|
p_person->SubState=SUB_STATE_STOPPING_OT;
|
|
}
|
|
else
|
|
if (WITHIN(p_person->Draw.Tweened->FrameIndex, 3, 3))
|
|
{
|
|
// jump frame found
|
|
set_person_running_stop(p_person,1);
|
|
}
|
|
*/
|
|
|
|
break;
|
|
|
|
case SUB_STATE_RUNNING_THEN_JUMP:
|
|
//LogText(" running \n");
|
|
|
|
if(check_on_slippy_slope(p_person))
|
|
return;
|
|
change_velocity_to(p_person,32);
|
|
person_normal_move(p_person);
|
|
person_normal_animate(p_person);
|
|
|
|
//
|
|
// Put some leeway in the jump frames so she jumps
|
|
// more responsively.
|
|
//
|
|
|
|
if (WITHIN(p_person->Draw.Tweened->FrameIndex, 0, 1))
|
|
{
|
|
set_person_running_jump_lr(p_person,0);
|
|
}
|
|
else
|
|
if (WITHIN(p_person->Draw.Tweened->FrameIndex, 3, 4))
|
|
{
|
|
// jump frame found
|
|
set_person_running_jump_lr(p_person,1);
|
|
}
|
|
|
|
/*
|
|
if (WITHIN(p_person->Draw.Tweened->FrameIndex, 3, 3))
|
|
{
|
|
set_person_running_jump_lr(p_person,2);
|
|
}
|
|
else
|
|
if (WITHIN(p_person->Draw.Tweened->FrameIndex, 7, 7))
|
|
{
|
|
// jump frame found
|
|
set_person_running_jump_lr(p_person,3);
|
|
}
|
|
*/
|
|
|
|
break;
|
|
|
|
case SUB_STATE_STOPPING:
|
|
case SUB_STATE_STOPPING_DEAD:
|
|
if(check_on_slippy_slope(p_person))
|
|
return;
|
|
end=person_normal_animate(p_person);
|
|
change_velocity_to(p_person,0);
|
|
|
|
if(p_person->Velocity<5)
|
|
{
|
|
// set_person_locked_idle_ready(p_person);
|
|
set_person_idle(p_person);
|
|
plant_feet(p_person);
|
|
}
|
|
|
|
break;
|
|
break;
|
|
|
|
|
|
case SUB_STATE_STOPPING_OT:
|
|
// case SUB_STATE_STOPPING:
|
|
end=person_normal_animate(p_person);
|
|
//trickle_velocity_to(p_person,0);
|
|
//change_velocity_to(p_person,0);
|
|
|
|
if( (p_person->Draw.Tweened->FrameIndex<2))
|
|
person_normal_move(p_person);
|
|
else
|
|
if( (p_person->Draw.Tweened->FrameIndex==2))
|
|
{
|
|
ASSERT(0);
|
|
if(p_person->SubState==SUB_STATE_STOPPING_OT)
|
|
p_person->Draw.Tweened->Locked=SUB_OBJECT_RIGHT_FOOT;
|
|
else
|
|
p_person->Draw.Tweened->Locked=SUB_OBJECT_LEFT_FOOT;
|
|
p_person->Velocity=0;
|
|
}
|
|
/*
|
|
MSG_add("stopping vel %d",p_person->Velocity);
|
|
if( (p_person->Draw.Tweened->FrameIndex==0))
|
|
end=person_normal_animate(p_person);
|
|
else
|
|
if( (p_person->Draw.Tweened->FrameIndex==1))
|
|
end=person_normal_animate_tween(p_person,64);
|
|
else
|
|
end=person_normal_animate(p_person);
|
|
|
|
if( (p_person->Draw.Tweened->FrameIndex<2))
|
|
trickle_velocity_to(p_person,0);
|
|
else
|
|
change_velocity_to(p_person,0);
|
|
// p_person->Velocity=0;
|
|
|
|
person_normal_move(p_person);
|
|
|
|
if(end==1)
|
|
p_person->Velocity=0;
|
|
else
|
|
trickle_velocity_to(p_person,0);
|
|
|
|
// change_velocity_to(p_person,0);
|
|
*/
|
|
if(end) //p_person->Velocity<1)
|
|
{
|
|
set_person_locked_idle_ready(p_person);
|
|
plant_feet(p_person);
|
|
p_person->Draw.Tweened->Locked=0; //SUB_OBJECT_LEFT_FOOT;
|
|
}
|
|
break;
|
|
case SUB_STATE_HOP_BACK:
|
|
|
|
//change_velocity_to(p_person,-10);
|
|
//person_normal_move(p_person);
|
|
//end = person_backwards_animate(p_person);
|
|
|
|
end=person_normal_animate(p_person);
|
|
person_normal_animate(p_person);
|
|
if(end==1&&p_person->SubState==SUB_STATE_HOP_BACK)
|
|
set_person_locked_idle_ready(p_person);
|
|
|
|
break;
|
|
case SUB_STATE_STEP_LEFT:
|
|
end=person_normal_animate(p_person);
|
|
|
|
if(end==1)
|
|
{
|
|
set_person_locked_idle_ready(p_person);
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_STEP_RIGHT:
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
set_person_locked_idle_ready(p_person);
|
|
}
|
|
break;
|
|
case SUB_STATE_FLIPING:
|
|
if(p_person->Draw.Tweened->FrameIndex>5)
|
|
// set_thing_velocity(p_person,24);
|
|
change_velocity_to_slow(p_person,20);
|
|
else
|
|
if(p_person->Draw.Tweened->FrameIndex>1)
|
|
set_thing_velocity(p_person,50);
|
|
// change_velocity_to(p_person,40);
|
|
|
|
|
|
if(p_person->Draw.Tweened->FrameIndex<11)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG angle;
|
|
angle=p_person->Draw.Tweened->Angle;
|
|
if(p_person->Genus.Person->Action==ACTION_FLIP_LEFT)
|
|
{
|
|
angle+=512;
|
|
}
|
|
else
|
|
angle-=512;
|
|
|
|
angle&=2047;
|
|
dx = -(SIN(angle) * p_person->Velocity) >> 8;
|
|
dz = -(COS(angle) * p_person->Velocity) >> 8;
|
|
person_normal_move_dxdz(p_person,dx,dz);
|
|
|
|
if(check_on_slippy_slope(p_person))
|
|
return;
|
|
}
|
|
|
|
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
/*
|
|
if(continue_action(p_person))
|
|
{
|
|
switch(p_person->Genus.Person->Action)
|
|
{
|
|
case ACTION_FLIP_LEFT:
|
|
// set_person_locked_idle_ready(p_person);
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_FLIP_LEFT_CONT); //,SUB_OBJECT_LEFT_FOOT);
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
if(!foot_hold_available(p_person,100,0,0))
|
|
{
|
|
set_person_locked_idle_ready(p_person);
|
|
}
|
|
// p_person->Draw.Tweened->NextFrame=global_anim_array[p_person->Genus.Person->AnimType][ANIM_FLIP_LEFT_CONT];
|
|
break;
|
|
case ACTION_FLIP_RIGHT:
|
|
locked_anim_change(p_person,SUB_OBJECT_LEFT_FOOT,ANIM_FLIP_RIGHT_CONT); //,SUB_OBJECT_LEFT_FOOT);
|
|
p_person->Draw.Tweened->FrameIndex=0;
|
|
if(!foot_hold_available(p_person,-100,0,0))
|
|
{
|
|
set_person_locked_idle_ready(p_person);
|
|
}
|
|
// set_person_locked_idle_ready(p_person);
|
|
// set_anim(p_person,ANIM_FLIP_RIGHT_CONT); //,SUB_OBJECT_LEFT_FOOT);
|
|
// p_person->Draw.Tweened->NextFrame=global_anim_array[p_person->Genus.Person->AnimType][ANIM_FLIP_RIGHT_CONT];
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
*/
|
|
set_locked_anim(p_person,ANIM_STAND_READY,SUB_OBJECT_LEFT_FOOT);
|
|
plant_feet(p_person);
|
|
if(p_person->State!=STATE_DANGLING)
|
|
set_person_locked_idle_ready(p_person);
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
p_person->Genus.Person->pcom_colour=20; // 50 game turns of not going into fight mode, pcom_colour reuse GOD SAVE US ALL
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
}
|
|
p_person->Velocity=0;
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Bike riding substates...
|
|
//
|
|
|
|
case SUB_STATE_MOUNTING_BIKE:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
/*
|
|
//dog poo
|
|
if(!p_person->Genus.Person->Channel)
|
|
p_person->Genus.Person->Channel=play_object_wave(p_person->Genus.Person->Channel,p_person,S_BIKE_IDLE,WAVE_PLAY_NO_INTERUPT|WAVE_LOOP);
|
|
#ifdef USE_A3D
|
|
// if(p_person->Genus.Person->Channel)
|
|
// A3DPosition(person->Genus.Person->Channel,p_person->WorldPos.X,p_person->WorldPos.Y,p_person->WorldPos.Z);
|
|
#endif
|
|
*/
|
|
if (end == 1)
|
|
{
|
|
p_person->SubState = SUB_STATE_RIDING_BIKE;
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_RIDING_BIKE:
|
|
|
|
// person_normal_animate(p_person);
|
|
|
|
{
|
|
Thing *p_bike = TO_THING(p_person->Genus.Person->InCar);
|
|
|
|
//
|
|
// Move to the same position above the bike.
|
|
//
|
|
|
|
GameCoord newpos = p_bike->WorldPos;
|
|
|
|
move_thing_on_map(p_person,&newpos);
|
|
|
|
// newpos.Y += 0x1000;
|
|
|
|
//
|
|
// The code to animate the person it all done in the engine nowaday...
|
|
// just before the person is drawn.
|
|
//
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_DISMOUNTING_BIKE:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end == 1)
|
|
{
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_BIKING;
|
|
p_person->Genus.Person->InCar = 0;
|
|
p_person->Draw.Tweened->Tilt = 0;
|
|
p_person->Draw.Tweened->Roll = 0;
|
|
|
|
set_person_idle(p_person);
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_SIMPLE_ANIM:
|
|
|
|
//
|
|
// A simple animation (maybe a taunt) set of by PCOM_set_person_move_animation()
|
|
//
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
|
|
|
|
if (end == 1)
|
|
{
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_NO_RETURN_TO_NORMAL)
|
|
{
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_NO_RETURN_TO_NORMAL;
|
|
|
|
p_person->SubState = SUB_STATE_SIMPLE_ANIM_OVER;
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim==ANIM_VALVE_LOOP)
|
|
{
|
|
p_person->Genus.Person->Timer1--;
|
|
if(p_person->Genus.Person->Timer1<=0)
|
|
set_anim(p_person,ANIM_VALVE_END);
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim==ANIM_VALVE_END)
|
|
set_person_locked_idle_ready(p_person);
|
|
// set_person_idle(p_person);
|
|
else
|
|
set_person_idle(p_person);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_SIMPLE_ANIM_OVER:
|
|
|
|
if (p_person->Draw.Tweened->CurrentAnim == ANIM_SIT_DOWN ||
|
|
p_person->Draw.Tweened->CurrentAnim == ANIM_SIT_IDLE)
|
|
{
|
|
//
|
|
// Every once in a while do an idle anim...
|
|
//
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
if ((PTIME(p_person) & 0x3) == 0)
|
|
{
|
|
p_person->Genus.Person->Timer1 += 1;
|
|
|
|
if (p_person->Genus.Person->Timer1 < 40)
|
|
{
|
|
p_person->Genus.Person->Health += 1;
|
|
|
|
if (p_person->Genus.Person->PersonType == PERSON_ROPER)
|
|
{
|
|
SATURATE(p_person->Genus.Person->Health, 0, 400);
|
|
}
|
|
else
|
|
{
|
|
SATURATE(p_person->Genus.Person->Health, 0, 200);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (((GAME_TURN + THING_NUMBER(p_person) * 8) & 0x3f) < 4)
|
|
{
|
|
set_person_do_a_simple_anim(p_person, ANIM_SIT_IDLE);
|
|
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NO_RETURN_TO_NORMAL;
|
|
}
|
|
}
|
|
else
|
|
if (p_person->Draw.Tweened->CurrentAnim == ANIM_HANDS_UP ||
|
|
p_person->Draw.Tweened->CurrentAnim == ANIM_HANDS_UP_LOOP)
|
|
{
|
|
//
|
|
// Every once in a while do an idle anim...
|
|
//
|
|
|
|
if (((GAME_TURN + THING_NUMBER(p_person) * 8) & 0x3f) < 4)
|
|
{
|
|
set_person_do_a_simple_anim(p_person, ANIM_HANDS_UP_LOOP);
|
|
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NO_RETURN_TO_NORMAL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
person_normal_animate(p_person);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
MSG_add("MOVEING unknow substate %d \n",p_person->SubState);
|
|
set_person_idle(p_person);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
void set_person_ko_recoil(Thing *p_person,SLONG anim,UBYTE flags)
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim==anim && p_person->Draw.Tweened->FrameIndex<5)
|
|
{
|
|
// if(p_person->Draw.Tweened->CurrentFrame!=p_person->Draw.Tweened->NextFrame)
|
|
if(!(p_person->Draw.Tweened->CurrentFrame->Flags&ANIM_FLAG_LAST_FRAME))
|
|
return;
|
|
}
|
|
if(p_person->SubState == SUB_STATE_DYING_GET_UP_AGAIN)
|
|
{
|
|
set_anim(p_person, anim);
|
|
p_person->SubState = SUB_STATE_DYING_KNOCK_DOWN_WAIT;
|
|
}
|
|
else
|
|
{
|
|
SLONG last_anim = p_person->Draw.Tweened->CurrentAnim;
|
|
|
|
set_locked_anim(p_person, anim,SUB_OBJECT_PELVIS);
|
|
|
|
if (last_anim == ANIM_GRAB_ARM_THROWV)
|
|
{
|
|
//
|
|
// This person was not lying in the direction of
|
|
// his angle. When he played the stomped on anim
|
|
// he flipped to a new angle. We change his angle here
|
|
// so it doesn't look like he moves.
|
|
//
|
|
|
|
// p_person->Draw.Tweened->Angle += 400;
|
|
|
|
//
|
|
// MY GOD! This doesn't work- we're going to need a rotate
|
|
// around pelvis function!
|
|
//
|
|
}
|
|
}
|
|
}
|
|
|
|
void set_person_recoil(Thing *p_person,SLONG anim,UBYTE flags)
|
|
{
|
|
if(p_person->SubState == SUB_STATE_DRAW_ITEM)
|
|
return;
|
|
|
|
if(p_person->State==STATE_JUMPING)
|
|
return;
|
|
|
|
if(p_person->SubState==SUB_STATE_CANNING_RELEASE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(p_person->SubState == SUB_STATE_DYING_GET_UP_AGAIN)
|
|
{
|
|
return;
|
|
|
|
}
|
|
if(p_person->State==STATE_DYING || p_person->State==STATE_DEAD)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(p_person->State==STATE_DANGLING)
|
|
{
|
|
if(p_person->SubState!=SUB_STATE_DROP_DOWN && p_person->SubState!=SUB_STATE_DROP_DOWN_LAND)
|
|
{
|
|
MFX_stop(THING_NUMBER(p_person), S_ZIPWIRE); //just incase we are on zipwire, dont bother with condition it will just bloat code
|
|
set_person_drop_down(p_person,0);
|
|
}
|
|
return;
|
|
}
|
|
if(p_person->Genus.Person->Flags & FLAG_PERSON_BIKING)
|
|
{
|
|
//throw person off bike because he's been hit/shot
|
|
set_person_dead(p_person,0,PERSON_DEATH_TYPE_STAY_ALIVE,0,0);
|
|
return;
|
|
|
|
|
|
}
|
|
if(p_person->State==STATE_CLIMB_LADDER)
|
|
{
|
|
set_person_drop_down(p_person,0);
|
|
return;
|
|
}
|
|
if(p_person->SubState==SUB_STATE_GRAPPLE_HOLD||p_person->SubState==SUB_STATE_GRAPPLE_ATTACK)
|
|
{
|
|
//
|
|
// take hit while grappleing, hmmmmmm
|
|
//
|
|
|
|
//
|
|
// better let go of person we are grappelling
|
|
//
|
|
|
|
|
|
set_person_fight_idle(TO_THING(p_person->Genus.Person->Target));
|
|
// return;
|
|
}
|
|
if(p_person->SubState==SUB_STATE_GRAPPLE_HELD)
|
|
{
|
|
//
|
|
// don't really have any sensible options here
|
|
//
|
|
return;
|
|
}
|
|
|
|
if (p_person->Genus.Person->Flags2 & FLAG2_PERSON_CARRYING)
|
|
{
|
|
emergency_uncarry(p_person);
|
|
}
|
|
|
|
if(p_person->State==STATE_HIT_RECOIL && p_person->Draw.Tweened->CurrentAnim==anim && p_person->Draw.Tweened->FrameIndex<2)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
p_person->OldState = p_person->State;
|
|
set_anim(p_person, anim); //,SUB_OBJECT_PELVIS);
|
|
p_person->SubState = 0;
|
|
set_generic_person_state_function(p_person, STATE_HIT_RECOIL);
|
|
|
|
//
|
|
// Remember the state this person was in before we recoil them,
|
|
// so that at the end of the recoil we can try to carry on what
|
|
// we were doing.
|
|
//
|
|
|
|
// p_person->Genus.Person->Mode = PERSON_MODE_FIGHT;
|
|
|
|
//
|
|
// Everything else sets these flags so why dont we...
|
|
//
|
|
|
|
// p_person->Genus.Person->Flags|=(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
}
|
|
|
|
void fn_person_recoil(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
|
|
SlideSoundCheck(p_person);
|
|
|
|
end = person_normal_animate(p_person);
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_KICK_NAD_TAKE:
|
|
if(end)
|
|
set_anim(p_person,ANIM_KICK_NAD_STUNNED);
|
|
return;
|
|
break;
|
|
case ANIM_KICK_NAD_STUNNED:
|
|
if(end)
|
|
set_anim(p_person,ANIM_KICK_NAD_RECOVER);
|
|
return;
|
|
case ANIM_KICK_NAD_RECOVER:
|
|
if(end)
|
|
goto finish;
|
|
return;
|
|
}
|
|
|
|
if(p_person->Draw.Tweened->FrameIndex==0)
|
|
{
|
|
SLONG old_velocity;
|
|
//
|
|
// little nudge back
|
|
//
|
|
old_velocity=p_person->Velocity;
|
|
p_person->Velocity=-4;
|
|
person_normal_move(p_person);
|
|
p_person->Velocity=old_velocity;
|
|
|
|
}
|
|
|
|
else
|
|
if(p_person->Draw.Tweened->FrameIndex==1)
|
|
{
|
|
//
|
|
// fair enough you can continue moveing now if you want
|
|
//
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
if(person_has_gun_out(p_person))
|
|
{
|
|
p_person->Genus.Person->Action = ACTION_AIM_GUN;
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Action=ACTION_IDLE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
if (end == 1)
|
|
{
|
|
finish:;
|
|
if(p_person->Genus.Person->Mode==PERSON_MODE_FIGHT)
|
|
set_person_fight_idle(p_person);
|
|
else
|
|
set_person_idle(p_person);
|
|
//plant_feet(p_person);
|
|
}
|
|
}
|
|
|
|
#define FALL_DIR_STRANGE_LAND (-1)
|
|
#define FALL_DIR_LAND_ON_FRONT ( 0)
|
|
#define FALL_DIR_LAND_ON_BACK ( 1)
|
|
|
|
SLONG find_anim_fall_dir(SLONG anim)
|
|
{
|
|
switch(anim)
|
|
{
|
|
case ANIM_PLUNGE_BACKWARD://128
|
|
case ANIM_KD_FRONT_MID: //170
|
|
case ANIM_KD_FRONT_HI: //171
|
|
case ANIM_KD_BACK_HI: //173
|
|
case ANIM_KD_BACK_LOW: //174
|
|
return FALL_DIR_LAND_ON_BACK; //land on back
|
|
|
|
case ANIM_PLUNGE_START:
|
|
case ANIM_PLUNGE_FORWARD://129
|
|
case ANIM_KD_FRONT_LOW: //175
|
|
case ANIM_KD_BACK_MID: //172
|
|
case ANIM_HANDS_UP_LIE: //18 civ male
|
|
return FALL_DIR_LAND_ON_FRONT; //land on front
|
|
|
|
default:
|
|
return FALL_DIR_STRANGE_LAND; //strange land
|
|
}
|
|
}
|
|
|
|
|
|
void move_away_from_wall(Thing *p_person)
|
|
{
|
|
person_normal_move_dxdz(p_person,1,1);
|
|
}
|
|
|
|
void generate_bonus_item(Thing *p_person)
|
|
{
|
|
if(GET_SKILL(p_person)>=12 || ((p_person->Genus.Person->pcom_ai!=PCOM_AI_CIV) && (p_person->Genus.Person->Flags2&FLAG2_PERSON_FAKE_WANDER)&& (Random()&0xff)<34))
|
|
// if( ((p_person->Genus.Person->pcom_ai!=PCOM_AI_CIV) && (p_person->Genus.Person->Flags2&FLAG2_PERSON_FAKE_WANDER)&& (Random()&0xff)<34))
|
|
{
|
|
SLONG gx,gy,gz;
|
|
SLONG special=SPECIAL_HEALTH;
|
|
|
|
if(!(p_person->Genus.Person->Flags2&FLAG2_PERSON_FAKE_WANDER))
|
|
switch(Random()&3)
|
|
{
|
|
case 0:
|
|
special=SPECIAL_HEALTH;
|
|
break;
|
|
case 1:
|
|
special=SPECIAL_AMMO_PISTOL;
|
|
|
|
break;
|
|
case 2:
|
|
special=SPECIAL_AMMO_SHOTGUN;
|
|
|
|
break;
|
|
case 3:
|
|
special=SPECIAL_AMMO_AK47;
|
|
break;
|
|
|
|
}
|
|
find_nice_place_near_person(
|
|
p_person,
|
|
&gx,
|
|
&gy,
|
|
&gz);
|
|
|
|
Thing *p_gun = alloc_special(
|
|
special,
|
|
SPECIAL_SUBSTATE_NONE,
|
|
gx,
|
|
gy,
|
|
gz,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
SLONG part_bad(Thing *p_person,SLONG part)
|
|
{
|
|
SLONG track_x,track_y,track_z;
|
|
SLONG fy,dy;
|
|
|
|
|
|
if(p_person->Genus.Person->Ware)
|
|
return(0);
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
part,
|
|
&track_x,
|
|
&track_y,
|
|
&track_z);
|
|
|
|
track_x+=p_person->WorldPos.X>>8;
|
|
track_y+=p_person->WorldPos.Y>>8;
|
|
track_z+=p_person->WorldPos.Z>>8;
|
|
|
|
fy=PAP_calc_map_height_at(track_x,track_z);
|
|
|
|
dy=fy-track_y;
|
|
|
|
if(abs(dy)>256)
|
|
{
|
|
return(1);
|
|
}
|
|
return(0);
|
|
|
|
|
|
}
|
|
|
|
void fn_person_dying(Thing *p_person)
|
|
{
|
|
SLONG hit;
|
|
SLONG end;
|
|
SLONG backwards;
|
|
SWORD on_face;
|
|
SLONG height;
|
|
|
|
//
|
|
// Is this person's pelvis is below the ground, then
|
|
// raise him up!
|
|
//
|
|
|
|
if (p_person->Genus.Person->Ware)
|
|
{
|
|
//
|
|
// Don't do this inside warehouses!
|
|
//
|
|
}
|
|
else
|
|
{
|
|
SLONG pelvis_x;
|
|
SLONG pelvis_y;
|
|
SLONG pelvis_z;
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
0, // 0 => pelvis
|
|
&pelvis_x,
|
|
&pelvis_y,
|
|
&pelvis_z);
|
|
|
|
pelvis_x += p_person->WorldPos.X >> 8;
|
|
pelvis_y += p_person->WorldPos.Y >> 8;
|
|
pelvis_z += p_person->WorldPos.Z >> 8;
|
|
|
|
SLONG ground = PAP_calc_map_height_at(pelvis_x, pelvis_z);
|
|
|
|
if (pelvis_y < ground + 8)
|
|
{
|
|
//
|
|
// The pelvis is below ground level. Move the person up.
|
|
//
|
|
|
|
if (ground > pelvis_y + 0x80)
|
|
{
|
|
//
|
|
// This is too much to move the person by... something bad
|
|
// could be hapenning!
|
|
//
|
|
}
|
|
else
|
|
{
|
|
p_person->WorldPos.Y += ground + 8 - pelvis_y << 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_DYING_INITIAL_ANI:
|
|
|
|
//
|
|
// This person is doing the first bit of their die animation.
|
|
//
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
|
|
if(part_bad(p_person,SUB_OBJECT_LEFT_FOOT)||part_bad(p_person,SUB_OBJECT_HEAD))
|
|
{
|
|
p_person->Draw.Tweened->Angle+=100;
|
|
p_person->Draw.Tweened->Angle&=2047;
|
|
}
|
|
|
|
if (end == 1)
|
|
{
|
|
backwards = find_anim_fall_dir(p_person->Draw.Tweened->CurrentAnim);
|
|
|
|
if (backwards == FALL_DIR_STRANGE_LAND)
|
|
{
|
|
//
|
|
// This is not an animation we recognise- kill them straight away!
|
|
//
|
|
|
|
p_person->SubState = SUB_STATE_DYING_ACTUALLY_DIE; //dead
|
|
}
|
|
|
|
if ((height=height_above_anything(p_person,SUB_OBJECT_PELVIS,&on_face)) > 8)
|
|
{
|
|
//
|
|
// Pelvis a bit in the air so set person death fall
|
|
//
|
|
// ASSERT(0)
|
|
|
|
if (on_face == GRAB_FLOOR)
|
|
{
|
|
on_face = 0;
|
|
}
|
|
|
|
p_person->DY = -(4 << 8);
|
|
p_person->OnFace = on_face;
|
|
p_person->SubState = SUB_STATE_DYING_PRONE;
|
|
if(height>128)
|
|
{
|
|
switch(backwards)
|
|
{
|
|
case FALL_DIR_LAND_ON_BACK:
|
|
locked_anim_change(p_person,0,ANIM_PLUNGE_BACKWARD);
|
|
break;
|
|
|
|
case FALL_DIR_LAND_ON_FRONT:
|
|
locked_anim_change(p_person,0,ANIM_PLUNGE_FORWARD);
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
MSG_add(" pretty near floor backwards %d\n",backwards);
|
|
|
|
//
|
|
// This person is on the floor- so do the final death animation.
|
|
//
|
|
|
|
// p_person->WorldPos.Y-=(height-9)<<8; // mistake?
|
|
p_person->WorldPos.Y-=(height)<<8; // mistake?
|
|
// ASSERT(0);
|
|
|
|
switch(backwards)
|
|
{
|
|
case FALL_DIR_LAND_ON_BACK:
|
|
locked_anim_change(p_person,0,ANIM_KD_BACK_LAND);
|
|
break;
|
|
|
|
case FALL_DIR_LAND_ON_FRONT:
|
|
locked_anim_change(p_person,0,ANIM_KD_FRONT_LAND);
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
drop_current_gun(p_person,0);
|
|
|
|
p_person->SubState = SUB_STATE_DYING_FINAL_ANI;
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_DYING_FINAL_ANI:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
ASSERT(end == 0 || end == 1);
|
|
|
|
if (end == 1)
|
|
{
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_HYPOCHONDRIA ||
|
|
p_person->Genus.Person->pcom_ai == PCOM_AI_FIGHT_TEST)
|
|
{
|
|
set_generic_person_state_function(p_person, STATE_DEAD);
|
|
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
p_person->SubState = SUB_STATE_DEAD_INJURED;
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_KO)
|
|
{
|
|
p_person->SubState = SUB_STATE_DYING_KNOCK_DOWN; // be unconscious
|
|
}
|
|
else
|
|
{
|
|
p_person->SubState = SUB_STATE_DYING_ACTUALLY_DIE; // go dead
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_DYING_ACTUALLY_DIE:
|
|
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_HYPOCHONDRIA ||
|
|
p_person->Genus.Person->pcom_ai == PCOM_AI_FIGHT_TEST)
|
|
{
|
|
//
|
|
// These people don't actually die...
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_DEAD);
|
|
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
p_person->SubState = SUB_STATE_DEAD_INJURED;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Kill the person.
|
|
//
|
|
|
|
generate_bonus_item(p_person);
|
|
|
|
|
|
set_generic_person_state_function(p_person,STATE_DEAD);
|
|
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
p_person->Genus.Person->Action = ACTION_DEAD;
|
|
|
|
//
|
|
// The blood that appears under dead people.
|
|
//
|
|
|
|
drop_current_gun(p_person,0);
|
|
|
|
TRACKS_Bloodpool(p_person);
|
|
TRACKS_Bloodpool(p_person);
|
|
|
|
//
|
|
// A counter for the number of cops killed.
|
|
//
|
|
|
|
if (p_person->Genus.Person->PersonType == PERSON_COP)
|
|
{
|
|
extern UBYTE *EWAY_counter;
|
|
|
|
if (EWAY_counter[7] < 255)
|
|
{
|
|
EWAY_counter[7] += 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Drop all weapons
|
|
//
|
|
|
|
// drop_all_items(p_person);
|
|
p_person->SubState=0;
|
|
if(p_person->Genus.Person->pcom_ai!=PCOM_AI_SUICIDE)
|
|
{
|
|
if (is_person_guilty(p_person))
|
|
{
|
|
//
|
|
// killing guilty people decreases the crime rate.
|
|
//
|
|
|
|
CRIME_RATE -= 2;
|
|
|
|
SATURATE(CRIME_RATE, 0, 100);
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_CIV &&
|
|
p_person->Genus.Person->pcom_move == PCOM_MOVE_WANDER)
|
|
{
|
|
//
|
|
// Killing wandering civs increases the crime rate.
|
|
//
|
|
|
|
CRIME_RATE += 5;
|
|
|
|
SATURATE(CRIME_RATE, 0, 100);
|
|
}
|
|
}
|
|
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_DYING_KNOCK_DOWN:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end == 1)
|
|
{
|
|
//
|
|
// He's going to be ok!
|
|
//
|
|
|
|
move_away_from_wall(p_person);
|
|
p_person->SubState = SUB_STATE_DYING_KNOCK_DOWN_WAIT;
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
drop_current_gun(p_person,0);
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_DYING_KNOCK_DOWN_WAIT:
|
|
|
|
//
|
|
// Animate so we can take hits.
|
|
//
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
//
|
|
// The count up to the person getting up again.
|
|
//
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
if((p_person->Genus.Person->Flags&(FLAG_PERSON_REQUEST_BLOCK|FLAG_PERSON_REQUEST_KICK|FLAG_PERSON_REQUEST_PUNCH))) //|| (GAME_TURN&3)==THING_NUMBER(p_person))
|
|
{
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_REQUEST_BLOCK|FLAG_PERSON_REQUEST_KICK|FLAG_PERSON_REQUEST_PUNCH);
|
|
|
|
p_person->Genus.Person->Timer1+=20;
|
|
}
|
|
else
|
|
p_person->Genus.Person->Timer1+=5;
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Timer1+=2;
|
|
// p_person->Genus.Person->Timer1=0;
|
|
}
|
|
|
|
if(p_person->Genus.Person->Timer1++>200-(GET_SKILL(p_person)*8))
|
|
{
|
|
p_person->SubState = SUB_STATE_DYING_GET_UP_AGAIN;
|
|
|
|
//
|
|
// Which get up animation shall we use?
|
|
//
|
|
|
|
switch(person_is_lying_on_what(p_person))
|
|
{
|
|
case PERSON_ON_HIS_FRONT:
|
|
/*
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
PANEL_new_text(NULL,4000,"get up anim %d",p_person->Draw.Tweened->CurrentAnim);
|
|
}
|
|
*/
|
|
locked_anim_change(p_person,SUB_OBJECT_PELVIS,ANIM_KO_BEHIND_BIG_GU);
|
|
break;
|
|
|
|
case PERSON_ON_HIS_BACK:
|
|
|
|
if (part_bad(p_person,SUB_OBJECT_LEFT_FOOT))
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_PELVIS,ANIM_QUICK_GET_UP);
|
|
}
|
|
else
|
|
if(part_bad(p_person,SUB_OBJECT_HEAD))
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_PELVIS,ANIM_KO_BACK_GU);
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->PersonType == PERSON_DARCI || //&& count_gang(p_person))||
|
|
p_person->Genus.Person->PersonType == PERSON_THUG_RASTA ||
|
|
p_person->Genus.Person->PersonType == PERSON_THUG_RED ||
|
|
p_person->Genus.Person->PersonType == PERSON_THUG_GREY)
|
|
{
|
|
//
|
|
// A fast acrobatic animation.
|
|
//
|
|
|
|
|
|
locked_anim_change(p_person,SUB_OBJECT_PELVIS,ANIM_QUICK_GET_UP);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
PANEL_new_text(NULL,4000,"get up anim %d",p_person->Draw.Tweened->CurrentAnim);
|
|
}
|
|
*/
|
|
|
|
locked_anim_change(p_person,SUB_OBJECT_PELVIS,ANIM_KO_BACK_GU);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_DYING_GET_UP_AGAIN:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
// if(p_person->Draw.Tweened->FrameIndex>2)
|
|
|
|
if (end == 1)
|
|
{
|
|
p_person->Genus.Person->Flags &= ~(FLAG_PERSON_KO | FLAG_PERSON_HELPLESS);
|
|
|
|
//
|
|
// He is okay now.
|
|
//
|
|
|
|
if(p_person->Draw.Tweened->CurrentAnim==ANIM_FIGHT_STOMPED_FRONT ||p_person->Draw.Tweened->CurrentAnim==ANIM_FIGHT_STOMPED_BACK)
|
|
{
|
|
locked_anim_change(p_person,SUB_OBJECT_PELVIS,ANIM_KO_BACK_GU);
|
|
}
|
|
else
|
|
{
|
|
// set_person_idle(p_person);
|
|
set_person_locked_idle_ready(p_person);
|
|
plant_feet(p_person);
|
|
if(p_person->State==STATE_DANGLING)
|
|
return;
|
|
}
|
|
|
|
if(p_person->Genus.Person->pcom_ai==PCOM_AI_CIV)
|
|
{
|
|
void PCOM_set_person_ai_flee_place(Thing *p_person,SLONG scary_x,SLONG scary_z);
|
|
|
|
if (p_person->Genus.Person->pcom_bent & PCOM_BENT_ROBOT)
|
|
{
|
|
//
|
|
// Robotic people never run away.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
PCOM_set_person_ai_flee_place(p_person, p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_DYING_PRONE:
|
|
end = person_normal_animate(p_person);
|
|
|
|
//
|
|
// The person is falling in the middle of the dying animation.
|
|
//
|
|
|
|
if (p_person->Velocity > 0)
|
|
{
|
|
hit = projectile_move_thing(p_person,3+4); //+4 sets pelvis flag
|
|
}
|
|
else
|
|
{
|
|
hit = projectile_move_thing(p_person,2+4);
|
|
}
|
|
|
|
if (hit == 1 || hit == 100)
|
|
{
|
|
drop_current_gun(p_person,0);
|
|
|
|
//
|
|
// The person has hit the floor
|
|
//
|
|
|
|
backwards = find_anim_fall_dir(p_person->Draw.Tweened->CurrentAnim);
|
|
|
|
switch(backwards)
|
|
{
|
|
case FALL_DIR_STRANGE_LAND:
|
|
ASSERT(0);
|
|
break;
|
|
|
|
case FALL_DIR_LAND_ON_FRONT:
|
|
locked_anim_change(p_person,0,ANIM_KD_FRONT_LAND);
|
|
break;
|
|
|
|
case FALL_DIR_LAND_ON_BACK:
|
|
locked_anim_change(p_person,0,ANIM_KD_BACK_LAND);
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// The last animation before the person dies.
|
|
//
|
|
|
|
p_person->SubState = SUB_STATE_DYING_FINAL_ANI;
|
|
{
|
|
SLONG new_y,on_face;
|
|
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_HYPOCHONDRIA)
|
|
{
|
|
//
|
|
// These people always end up on the floor!
|
|
//
|
|
|
|
p_person->WorldPos.Y = PAP_calc_map_height_at(p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8) << 8;
|
|
p_person->OnFace = NULL;
|
|
}
|
|
else
|
|
{
|
|
on_face = find_face_for_this_pos(p_person->WorldPos.X>>8,p_person->WorldPos.Y>>8,p_person->WorldPos.Z>>8,&new_y,0,0);
|
|
if(on_face==GRAB_FLOOR)
|
|
{
|
|
}
|
|
else
|
|
if(on_face)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
new_y=PAP_calc_height_at_thing(p_person,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8);
|
|
}
|
|
|
|
if(abs((p_person->WorldPos.Y>>8)-new_y)<128)
|
|
{
|
|
p_person->WorldPos.Y=new_y<<8;
|
|
}
|
|
else
|
|
{
|
|
// ASSERT(0); //Tell MikeD
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
DrawTween dead_tween;
|
|
void init_dead_tween(void)
|
|
{
|
|
memset(&dead_tween,0,sizeof(DrawTween));
|
|
}
|
|
|
|
void fn_person_dead(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
UWORD try_respawn=0;
|
|
/*
|
|
if(CNET_network_game)
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
set_person_alive_alive_o(p_person);
|
|
return;
|
|
}
|
|
*/
|
|
SlideSoundCheck(p_person);
|
|
switch(p_person->SubState)
|
|
{
|
|
|
|
case SUB_STATE_DEAD_ARREST_TURN_OVER:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
SLONG c0;
|
|
set_anim(p_person,ANIM_ARREST_BE_CUFFED);
|
|
p_person->Draw.Tweened->Angle+=1024;
|
|
p_person->Draw.Tweened->Angle&=2047;
|
|
|
|
p_person->SubState=SUB_STATE_DEAD_CUFFED;
|
|
for(c0=0;c0<3;c0++)
|
|
{
|
|
advance_keyframe(p_person->Draw.Tweened);
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_DEAD_CUFFED:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
p_person->SubState=SUB_STATE_DEAD_ARRESTED;
|
|
// drop_all_items(p_person);
|
|
|
|
if (is_person_guilty(p_person))
|
|
{
|
|
//
|
|
// Arresting guilty people decreases the crime rate.
|
|
//
|
|
|
|
CRIME_RATE -= 4;
|
|
|
|
SATURATE(CRIME_RATE, 0, 100);
|
|
}
|
|
generate_bonus_item(p_person);
|
|
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_DEAD_ARRESTED:
|
|
try_respawn=1;
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
if(PTIME(p_person)==0) //once every 256 game turns
|
|
set_anim(p_person,ANIM_ARREST_STRUGGLE);
|
|
|
|
|
|
}
|
|
break;
|
|
case SUB_STATE_DEAD_RESPAWN:
|
|
extern SLONG PCOM_do_regen(Thing *p_person);
|
|
PCOM_do_regen(p_person);
|
|
break;
|
|
|
|
case SUB_STATE_PICKUP_CARRY_V:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
p_person->SubState = SUB_STATE_STAND_CARRY_V;
|
|
}
|
|
break;
|
|
case SUB_STATE_DROP_CARRY_V:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
p_person->SubState=SUB_STATE_DEAD_INJURED;
|
|
}
|
|
break;
|
|
case SUB_STATE_STAND_CARRY_V:
|
|
//
|
|
//
|
|
// If you ever add anything here then my sloppy coding down in default will fuck up
|
|
|
|
break;
|
|
case SUB_STATE_CARRY_MOVE_V:
|
|
end=person_normal_animate(p_person);
|
|
break;
|
|
|
|
case SUB_STATE_DEAD_INJURED:
|
|
|
|
//
|
|
// Do a groan once in a while...
|
|
//
|
|
|
|
if ((PTIME(p_person) & 0x1f) == 0 && (Random() & 0xff) < 50)
|
|
{
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_FIGHT_TEST && (p_person->Flags & FLAGS_IN_VIEW) && person_is_lying_on_what(p_person) == PERSON_ON_HIS_BACK)
|
|
{
|
|
//
|
|
// This person is lying on his back and is in view- he had
|
|
// better not do his anim or he'll visibly flip.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
set_anim(p_person, ANIM_INJURED_LOOP_STRUGGLE);
|
|
}
|
|
}
|
|
|
|
person_normal_animate(p_person);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_SUICIDE)
|
|
{
|
|
//
|
|
// Suicide people are important to the level so can't be deleted.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
if(!p_person->Genus.Person->PlayerID)
|
|
try_respawn=1;
|
|
|
|
//
|
|
// dont respawn if we are doing something with them ,like searching them
|
|
//
|
|
if(NET_PERSON(0)->Genus.Person->Target==THING_NUMBER(p_person))
|
|
try_respawn=0;
|
|
|
|
/*
|
|
if(!(p_person->Flags & FLAGS_IN_VIEW))
|
|
{
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
}
|
|
*/
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
if (PersonIsMIB(p_person))
|
|
{
|
|
if (p_person->Genus.Person->Timer1 >= 20 * 20 * 5) // Was 32 * 20 * 5 for the PC, less time for the DC...
|
|
{
|
|
if (p_person->Genus.Person->Timer1 != 0xffff)
|
|
{
|
|
SLONG px;
|
|
SLONG py;
|
|
SLONG pz;
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_PELVIS,
|
|
&px,
|
|
&py,
|
|
&pz);
|
|
|
|
px <<= 8;
|
|
py <<= 8;
|
|
pz <<= 8;
|
|
|
|
px += p_person->WorldPos.X;
|
|
py += p_person->WorldPos.Y;
|
|
pz += p_person->WorldPos.Z;
|
|
|
|
//
|
|
// Make this person blow up!
|
|
//
|
|
|
|
/* POW_create(
|
|
POW_CREATE_LARGE_SEMI,
|
|
px,
|
|
py,
|
|
pz,0,0,0);*/
|
|
|
|
//
|
|
// Massive lightning strike
|
|
//
|
|
|
|
SPARK_Pinfo p1;
|
|
SPARK_Pinfo p2;
|
|
UBYTE i;
|
|
|
|
PARTICLE_Add(px,py,pz,0,0,0,POLY_PAGE_BLOOM1,0,0xffFFFFFF,PFLAG_FADE,40,255,1,-5,0);
|
|
|
|
for (i=0;i<20;i++)
|
|
{
|
|
PARTICLE_Add(px+((Random()&0x9ff)-0x4ff),
|
|
py+((Random()&0x9ff)-0x4ff),
|
|
pz+((Random()&0x9ff)-0x4ff),
|
|
(Random()&0x1ff)-0xff,256+(Random()&0x3ff),(Random()&0x1ff)-0x7f,
|
|
POLY_PAGE_SMOKECLOUD2,2+((Random()&3)<<2),0x7F7fFFFF,
|
|
PFLAG_SPRITEANI|PFLAG_SPRITELOOP|PFLAG_FADE|PFLAG_RESIZE,
|
|
300,70,1,2,2);
|
|
DIRT_new_sparks(px>>8,py>>8,pz>>8,2);
|
|
}
|
|
|
|
// MFX_play_ambient(0,S_THUNDER_END-(Random()&1),0);
|
|
MFX_stop(THING_NUMBER(p_person),S_MIB_LEVITATE);
|
|
MFX_play_thing(THING_NUMBER(p_person),S_MIB_EXPLODE,0,p_person);
|
|
|
|
px>>=8; py>>=8; pz>>=8;
|
|
|
|
|
|
for (i=0;i<10;i++)
|
|
{
|
|
p1.type = SPARK_TYPE_POINT;
|
|
p1.flag = 0;
|
|
p1.person = 0;
|
|
p1.limb = 0;
|
|
p1.x=px+(Random()&0x3f)-0x1f;
|
|
p1.y=py+1000;
|
|
p1.z=pz+(Random()&0x3f)-0x1f;
|
|
p2.type = SPARK_TYPE_POINT;
|
|
p2.flag = 0;
|
|
p2.person = 0;
|
|
p2.limb = 0;
|
|
p2.x=px+(Random()&0x3f)-0x1f;
|
|
p2.y=PAP_calc_map_height_at(px,pz);
|
|
p2.z=pz+(Random()&0x3f)-0x1f;
|
|
|
|
SPARK_create(
|
|
&p1,
|
|
&p2,
|
|
25+(Random()&0xf));
|
|
DIRT_new_sparks(p2.x,p2.y,p2.z,2);
|
|
|
|
}
|
|
|
|
create_shockwave(
|
|
px,
|
|
py,
|
|
pz,
|
|
0x300,
|
|
200,
|
|
p_person);
|
|
|
|
DIRT_gust(p_person,px,pz,px+400,pz);
|
|
|
|
remove_thing_from_map(p_person);
|
|
}
|
|
|
|
p_person->Genus.Person->Timer1 = 0xffff;
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Timer1 += 16 * TICK_RATIO >> TICK_SHIFT;
|
|
}
|
|
}
|
|
else
|
|
if(try_respawn) //MIB's dont respawn
|
|
{
|
|
SLONG vanish_time;
|
|
#ifdef PSX
|
|
#define TIMER_VANISH 0
|
|
#else
|
|
#define TIMER_VANISH 100
|
|
#endif
|
|
|
|
vanish_time=TIMER_VANISH;
|
|
|
|
if(VIOLENCE==0)
|
|
vanish_time=30;
|
|
|
|
#ifdef PSX
|
|
extern UBYTE remove_dead_people;
|
|
if(remove_dead_people)
|
|
{
|
|
goto remove_them;
|
|
}
|
|
#endif
|
|
|
|
if( ( p_person->Flags & FLAGS_IN_VIEW) && ( VIOLENCE!=0 ) )
|
|
{
|
|
// Person is still in view, and we're allowed violence,
|
|
// so reset the timer.
|
|
p_person->Genus.Person->InsideRoom = 0;
|
|
}
|
|
|
|
|
|
if((!(p_person->Flags & FLAGS_IN_VIEW)) ||VIOLENCE==0)
|
|
{
|
|
// if(VIOLENCE==0)
|
|
// p_person->WorldPos.Y-=256;
|
|
p_person->Genus.Person->InsideRoom++; //timer
|
|
//#ifndef PSX
|
|
if(p_person->Genus.Person->InsideRoom>vanish_time)//TIMER_VANISH)
|
|
//#endif
|
|
{
|
|
#ifdef PSX
|
|
remove_them:;
|
|
#endif
|
|
if(p_person->Genus.Person->Flags2&FLAG2_PERSON_FAKE_WANDER )
|
|
{
|
|
drop_all_items(p_person,0);
|
|
remove_thing_from_map(p_person);
|
|
|
|
p_person->SubState=SUB_STATE_DEAD_RESPAWN;
|
|
}
|
|
else
|
|
if(p_person->Genus.Person->pcom_ai == PCOM_AI_CIV && p_person->Genus.Person->pcom_move == PCOM_MOVE_WANDER)
|
|
{
|
|
remove_thing_from_map(p_person);
|
|
p_person->SubState=SUB_STATE_STAND_CARRY_V; // do nowt from now on
|
|
// p_person->SubState=SUB_STATE_DEAD_RESPAWN;
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// gone vanished kaput
|
|
#ifdef PSX //
|
|
drop_all_items(p_person,0);
|
|
remove_thing_from_map(p_person);
|
|
|
|
p_person->SubState=SUB_STATE_STAND_CARRY_V; // do nowt from now on
|
|
|
|
free_draw_tween(p_person->Draw.Tweened);
|
|
p_person->Draw.Tweened=&dead_tween;//&DRAW_TWEENS[0]; // lets see if this crashes it
|
|
#else
|
|
if(VIOLENCE==0)
|
|
{
|
|
drop_all_items(p_person,0);
|
|
remove_thing_from_map(p_person);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
//#endif
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->InsideRoom=0; //timer
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SLONG dist_from_a_to_b(Thing *a,Thing *b)
|
|
{
|
|
SLONG dx,dz,dist;
|
|
|
|
dx=(a->WorldPos.X-b->WorldPos.X)>>8;
|
|
dz=(a->WorldPos.Z-b->WorldPos.Z)>>8;
|
|
|
|
dx=abs(dx);
|
|
dz=abs(dz);
|
|
|
|
dist=QDIST2(dx,dz);
|
|
return(dist);
|
|
}
|
|
|
|
|
|
void player_aim_at_new_person(Thing *p_person,UWORD new_target)
|
|
{
|
|
SLONG pitch;
|
|
Thing *p_target;
|
|
|
|
ASSERT(p_person->Genus.Person->PlayerID);
|
|
|
|
p_target=TO_THING(new_target);
|
|
|
|
pitch=get_pitch_to_thing_quick(p_person,p_target);
|
|
pitch-=1024;
|
|
pitch&=2047;
|
|
|
|
turn_to_face_thing_quick(p_person,p_target);
|
|
|
|
//extern SLONG FC_focus_yaw;
|
|
|
|
// FC_focus_yaw=p_person->Draw.Tweened->Angle;
|
|
// FC_position_for_lookaround(pitch);
|
|
extern void set_look_pitch(SLONG p);
|
|
set_look_pitch(pitch);
|
|
|
|
|
|
|
|
}
|
|
|
|
SLONG get_angle_to_target(Thing *p_person)
|
|
{
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
SLONG dx,dz;
|
|
SLONG angle;
|
|
|
|
// if(p_target->Class==CLASS_PERSON)
|
|
{
|
|
dx=(p_target->WorldPos.X-p_person->WorldPos.X)>>8;
|
|
dz=(p_target->WorldPos.Z-p_person->WorldPos.Z)>>8;
|
|
angle = (Arctan(dx,-dz)+1024+2048)&2047;
|
|
return(angle);
|
|
}
|
|
// return(-1);
|
|
}
|
|
|
|
SLONG player_running_aim_gun(Thing *p_person)
|
|
{
|
|
SLONG old_target=p_person->Genus.Person->Target;
|
|
if (p_person->Genus.Person->Target = find_target_new(p_person))
|
|
{
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
highlight_gun_target(p_person,p_target);
|
|
|
|
p_person->Flags|=FLAGS_PERSON_AIM_AND_RUN;
|
|
p_person->Draw.Tweened->AngleTo = get_angle_to_target(p_person);
|
|
|
|
if(old_target!=p_person->Genus.Person->Target)
|
|
{
|
|
if(p_person->Genus.Person->PersonType==PERSON_DARCI)
|
|
{
|
|
|
|
|
|
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
//
|
|
// You can target bats/barrels/cars now aswell...
|
|
//
|
|
|
|
if (p_target->Class == CLASS_PERSON)
|
|
{
|
|
if(might_i_be_a_villain(p_target))
|
|
{
|
|
PCOM_cop_aiming_at_you(p_target,p_person);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void twist_darci_body_to_angle(Thing *p_person, SLONG twist)
|
|
{
|
|
UWORD ahead;
|
|
UWORD left;
|
|
UWORD right;
|
|
|
|
DrawTween *dt = p_person->Draw.Tweened;
|
|
|
|
if (twist > 1024)
|
|
{
|
|
twist -= 2048;
|
|
}
|
|
|
|
twist -= twist >> 3;
|
|
|
|
//
|
|
// The anim to use depends on the gun.
|
|
//
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
//
|
|
// The pistol.
|
|
//
|
|
|
|
ahead = ANIM_PISTOL_AIM_AHEAD;
|
|
left = ANIM_POINT_GUN_LEFT;
|
|
right = ANIM_POINT_GUN_RIGHT;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Some other type of gun.
|
|
//
|
|
/*
|
|
if ((p_person->Genus.Person->PersonType==PERSON_ROPER)&&((p_person->Draw.Tweened->PersonID>>5)==5)) {
|
|
ahead = ANIM_AK_AIM;
|
|
left = ANIM_AK_AIM_L;
|
|
right = ANIM_AK_AIM_R;
|
|
} else
|
|
*/
|
|
{
|
|
ahead = ANIM_POINT_SHOTGUN_AHEAD;
|
|
left = ANIM_POINT_SHOTGUN_RIGHT;
|
|
right = ANIM_POINT_SHOTGUN_LEFT;
|
|
}
|
|
|
|
//twist = SIGN(twist) * 255;
|
|
}
|
|
|
|
if (twist == 0)
|
|
{
|
|
dt->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][ahead];
|
|
dt->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][ahead];
|
|
dt->AnimTween = 0;
|
|
}
|
|
else
|
|
if (twist < 0)
|
|
{
|
|
if (twist < -255)
|
|
{
|
|
twist = -255;
|
|
}
|
|
|
|
dt->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][ahead];
|
|
dt->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][left ];
|
|
dt->AnimTween = -twist;
|
|
}
|
|
else
|
|
{
|
|
if (twist > 255)
|
|
{
|
|
twist = 255;
|
|
}
|
|
|
|
dt->CurrentFrame = global_anim_array[p_person->Genus.Person->AnimType][ahead];
|
|
dt->NextFrame = global_anim_array[p_person->Genus.Person->AnimType][right];
|
|
dt->AnimTween = twist;
|
|
}
|
|
}
|
|
|
|
SLONG might_i_be_a_villain(Thing *p_person)
|
|
{
|
|
if(p_person->Genus.Person->PersonType==PERSON_DARCI||
|
|
p_person->Genus.Person->PersonType==PERSON_ROPER||
|
|
p_person->Genus.Person->PersonType==PERSON_COP||
|
|
p_person->Genus.Person->PersonType==PERSON_HOSTAGE)
|
|
return(0);
|
|
else
|
|
return(1);
|
|
|
|
}
|
|
|
|
SLONG am_i_a_thug(Thing *p_person)
|
|
{
|
|
if(p_person->Genus.Person->PersonType==PERSON_THUG_RASTA||
|
|
p_person->Genus.Person->PersonType==PERSON_THUG_GREY||
|
|
p_person->Genus.Person->PersonType==PERSON_THUG_RED||
|
|
p_person->Genus.Person->PersonType==PERSON_TRAMP)
|
|
return(1);
|
|
else
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// This needs to take into account the type of weapon, sniper is accurate at a distance etc
|
|
//
|
|
SLONG calc_dist_benefit_to_gun(Thing *p_person,SLONG dist)
|
|
{
|
|
SLONG benefit; //in thousandths of a second
|
|
|
|
|
|
|
|
/*
|
|
//
|
|
// I can't work out how these aim differently at distance
|
|
//
|
|
if(p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
|
|
|
|
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
switch (p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_SHOTGUN:
|
|
|
|
break;
|
|
case SPECIAL_AK47:
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// This isn't a weapon you shoot!
|
|
//
|
|
|
|
benefit=0;
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
|
|
if(dist<512)
|
|
{
|
|
benefit=(1024+300-(dist<<1));
|
|
|
|
}
|
|
else
|
|
{
|
|
benefit=500-(dist>>3);
|
|
}
|
|
|
|
|
|
if (benefit < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return benefit * TICK_RATIO >> TICK_SHIFT;
|
|
}
|
|
}
|
|
|
|
extern SLONG look_pitch;
|
|
void highlight_gun_target(Thing *p_person,Thing *p_target)
|
|
{
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
SLONG angle,dx,dy,dz;
|
|
|
|
if(dist_to_target(p_person,p_target)< (10<<8) )
|
|
track_gun_sight(p_target,256);
|
|
// ASSERT(dist_to_target(p_person,p_target)< (10<<8) );
|
|
|
|
#define MAKE_FPM_TRACK_ENEMY 1
|
|
|
|
#ifdef MAKE_FPM_TRACK_ENEMY
|
|
if(p_person->Genus.Person->Flags2&FLAG2_PERSON_LOOK)
|
|
{
|
|
//
|
|
// player is in first person look round mode, so take global look_pitch into account
|
|
//
|
|
|
|
//
|
|
// look_pitch is a bit odd, its 0 directly infront of you 1900 when looking up and 50 when looking down
|
|
//
|
|
|
|
dx = p_target->WorldPos.X - p_person->WorldPos.X >> 8;
|
|
dy = p_target->WorldPos.Y - p_person->WorldPos.Y >> 8;
|
|
dz = p_target->WorldPos.Z - p_person->WorldPos.Z >> 8;
|
|
|
|
angle = Arctan(dx*dx+dz*dz,dy*abs(dy)<<1);
|
|
angle=((-(angle-512))+2048)&2047;
|
|
|
|
|
|
angle-=look_pitch;
|
|
if(angle>1024)
|
|
angle-=2048;
|
|
if(angle<-1024)
|
|
angle+=2048;
|
|
|
|
if(angle<-8)
|
|
look_pitch-=8;
|
|
else
|
|
if(angle>8)
|
|
look_pitch+=8;
|
|
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
// track_gun_sight(p_target,p_target->);
|
|
}
|
|
return;
|
|
/*
|
|
if (p_person->Genus.Person->PlayerID ||
|
|
p_target->Genus.Person->PlayerID)
|
|
{
|
|
SLONG above;
|
|
|
|
//
|
|
// Draw a little mark above our targets head.
|
|
//
|
|
|
|
if (p_target->Class == CLASS_PERSON ||
|
|
p_target->Class == CLASS_VEHICLE)
|
|
{
|
|
above = 0xb000;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// A bat/barrel is not as tall as a person...
|
|
//
|
|
|
|
above = 0x4000;
|
|
}
|
|
|
|
AENG_world_line(
|
|
p_target->WorldPos.X >> 8,
|
|
p_target->WorldPos.Y + above >> 8,
|
|
p_target->WorldPos.Z >> 8,
|
|
16,
|
|
0xff0000,
|
|
p_target->WorldPos.X >> 8,
|
|
p_target->WorldPos.Y + above + 0x1000 >> 8,
|
|
p_target->WorldPos.Z >> 8,
|
|
0,
|
|
0x330088,
|
|
FALSE);
|
|
|
|
|
|
{
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
void fn_person_gun(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_DRAW_GUN:
|
|
|
|
end=person_normal_animate(p_person);
|
|
|
|
if( (p_person->Draw.Tweened->FrameIndex==3) || (p_person->Genus.Person->Flags&FLAG_PERSON_GUN_OUT)==0 )
|
|
{
|
|
p_person->Draw.Tweened->PersonID&= ~0xe0;
|
|
p_person->Draw.Tweened->PersonID|= 1<<5;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_GUN_OUT;
|
|
}
|
|
|
|
if (end==1)
|
|
{
|
|
set_person_aim(p_person);
|
|
|
|
//p_person->SubState=SUB_STATE_AIM_GUN;
|
|
//set_anim(p_person,ANIM_GUN_AIM);
|
|
//p_person->Genus.Person->Action=ACTION_AIM_GUN;
|
|
|
|
p_person->Genus.Person->Flags &= ~(FLAG_PERSON_NON_INT_C | FLAG_PERSON_NON_INT_M);
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_AIM_GUN:
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
SLONG twist;
|
|
SLONG old_target;
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
//
|
|
// Using a special.
|
|
//
|
|
|
|
|
|
if (p_special->Genus.Special->SpecialType == SPECIAL_AK47)
|
|
{
|
|
p_person->Genus.Person->Timer1+=TICK_TOCK;
|
|
if(p_person->Genus.Person->Timer1>100) // 1/10th of a second
|
|
if(continue_firing(p_person))
|
|
{
|
|
p_person->Genus.Person->Timer1=0; // 1/5th of a second
|
|
|
|
set_person_shoot(p_person, TRUE);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
old_target=p_person->Genus.Person->Target;
|
|
|
|
if (p_person->Genus.Person->Target = find_target_new(p_person))
|
|
{
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
if(p_target->SubState==SUB_STATE_DYING_KNOCK_DOWN_WAIT)
|
|
{
|
|
if(p_target->Genus.Person->pcom_ai==PCOM_AI_CIV)
|
|
p_target->Genus.Person->Timer1=0;
|
|
|
|
}
|
|
|
|
if(old_target!=p_person->Genus.Person->Target)
|
|
{
|
|
if(p_person->Genus.Person->PersonType==PERSON_DARCI)
|
|
{
|
|
Thing *p_target;
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
|
|
// if(p_person->Draw.Tweened->DRoll==0) //not spinning
|
|
//#ifndef PSX
|
|
|
|
//
|
|
// You can target bats/barrels/cars now aswell...
|
|
//
|
|
|
|
if (p_target->Class == CLASS_PERSON)
|
|
{
|
|
if(might_i_be_a_villain(p_target))
|
|
{
|
|
PCOM_cop_aiming_at_you(p_target,p_person);
|
|
//
|
|
//
|
|
//
|
|
if ((p_target->State != STATE_DEAD)&&(p_target->State != STATE_DYING))
|
|
{
|
|
SLONG sample;
|
|
switch(Random()&3)
|
|
{
|
|
case 0:
|
|
sample=S_DARCI_FREEZE_START;
|
|
break;
|
|
case 1:
|
|
sample=S_DARCI_FREEZE_END;
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
sample=S_DARCI_STOP_POLICE;
|
|
break;
|
|
}
|
|
if (IsEnglish)
|
|
MFX_play_thing(THING_NUMBER(p_person),sample,0,p_person);
|
|
}
|
|
}
|
|
}
|
|
//#endif
|
|
}
|
|
}
|
|
|
|
twist = get_dangle(p_person, p_target);
|
|
|
|
twist_darci_body_to_angle(p_person, twist);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No target so keep current twist!
|
|
//
|
|
}
|
|
}
|
|
else
|
|
{
|
|
person_normal_animate(p_person);
|
|
}
|
|
|
|
if (p_person->Genus.Person->Target)
|
|
{
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
highlight_gun_target(p_person,p_target);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
{
|
|
THING_INDEX target;
|
|
SLONG target_good=0;
|
|
end=person_normal_animate(p_person);
|
|
|
|
//
|
|
// don't need to do this every game turn
|
|
//
|
|
|
|
if (p_person->Genus.Person->PlayerID)
|
|
{
|
|
UWORD old_target;;
|
|
UWORD new_target;
|
|
|
|
old_target = p_person->Genus.Person->Target;
|
|
new_target = find_target(p_person);
|
|
|
|
if (new_target && old_target != new_target)
|
|
{
|
|
//if(old_target==0)
|
|
{
|
|
player_aim_at_new_person(p_person,new_target);
|
|
|
|
}
|
|
//
|
|
// Just targeted a new person.
|
|
//
|
|
|
|
p_person->Genus.Person->Target = new_target;
|
|
p_person->Genus.Person->Gunaim = MAX_GUN_AIM;
|
|
ASSERT(p_person->Genus.Person->Target != THING_NUMBER(p_person));
|
|
ASSERT(TO_THING(p_person->Genus.Person->Target)->Class==CLASS_PERSON);
|
|
}
|
|
|
|
if(new_target==0)
|
|
{
|
|
p_person->Genus.Person->Target=0;
|
|
|
|
}
|
|
else
|
|
{
|
|
target_good=1;
|
|
}
|
|
}
|
|
|
|
if (p_person->Genus.Person->Target)
|
|
{
|
|
Thing *p_target;
|
|
|
|
p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
//
|
|
// Improve this person's aim the longer he can see his target.
|
|
//
|
|
|
|
if (target_good || can_a_see_b(p_person, p_target))
|
|
{
|
|
SLONG dist,aimratio;
|
|
|
|
if (p_person->Genus.Person->PlayerID ||
|
|
p_target->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// This shoot-out involves the player- so put it on screen.
|
|
//
|
|
|
|
track_gun_sight(p_target,(p_person->Genus.Person->Gunaim*100)/MAX_GUN_AIM);
|
|
}
|
|
|
|
//
|
|
// How quickly the aim improves depends on the distance to the target.
|
|
//
|
|
|
|
dist = dist_from_a_to_b(p_person, p_target);
|
|
aimratio = calc_dist_benefit_to_gun(p_person,dist);
|
|
|
|
p_person->Genus.Person->Gunaim -= aimratio; // relate this to distance to target
|
|
|
|
//
|
|
// If the person is moving/turning then we can't get a good aim...
|
|
//
|
|
|
|
{
|
|
SLONG min_gunaim = abs(p_target->Velocity << 5) + abs(p_target->Draw.Tweened->Roll << 4);
|
|
|
|
if (p_person->Genus.Person->Gunaim < min_gunaim)
|
|
{
|
|
p_person->Genus.Person->Gunaim = min_gunaim;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Gunaim = MAX_GUN_AIM;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
break;
|
|
case SUB_STATE_SHOOT_GUN:
|
|
|
|
{
|
|
UWORD anim_speed = 256;
|
|
|
|
//
|
|
// We want the gun shooting to be faster.
|
|
//
|
|
|
|
if (p_person->Genus.Person->SpecialUse == NULL)
|
|
{
|
|
anim_speed = 400;
|
|
}
|
|
|
|
end=person_normal_animate_speed(p_person, anim_speed);
|
|
}
|
|
|
|
{
|
|
//
|
|
// Let's try some gun smoke
|
|
//
|
|
SLONG px,py,pz, alpha;
|
|
/*
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_RIGHT_HAND,
|
|
&px,
|
|
&py,
|
|
&pz);
|
|
|
|
px<<=8; py<<=8; pz<<=8;
|
|
px += p_person->WorldPos.X;
|
|
py += p_person->WorldPos.Y;
|
|
pz += p_person->WorldPos.Z;
|
|
*/
|
|
#ifndef BUILD_PSX
|
|
alpha=(0x6f-(p_person->Draw.Tweened->FrameIndex*4));
|
|
if (alpha>=0)
|
|
{
|
|
alpha<<=24;
|
|
|
|
PARTICLE_Add(
|
|
p_person->Genus.Person->GunMuzzle.X,
|
|
p_person->Genus.Person->GunMuzzle.Y,
|
|
p_person->Genus.Person->GunMuzzle.Z,
|
|
(Random()&0xff)-0x7f,0xff,(Random()&0xff)-0x7f,
|
|
POLY_PAGE_SMOKECLOUD2, 2+((Random()&3)<<2),
|
|
alpha|0x00FFFFFF,
|
|
PFLAG_SPRITEANI|PFLAG_SPRITELOOP|PFLAG_FADE|PFLAG_RESIZE,
|
|
150,28,1,8,1);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
if (end == 1)
|
|
{
|
|
SLONG firing_an_ak = FALSE;
|
|
SLONG fire_length = 4;
|
|
|
|
if (!p_person->Genus.Person->PlayerID && p_person->Genus.Person->SpecialUse && TO_THING(p_person->Genus.Person->SpecialUse)->Genus.Special->SpecialType == SPECIAL_AK47)
|
|
{
|
|
//
|
|
// This person is firing the AK47!
|
|
//
|
|
|
|
firing_an_ak = TRUE;
|
|
}
|
|
|
|
if (PersonIsMIB(p_person))
|
|
{
|
|
firing_an_ak = TRUE;
|
|
fire_length = 6;
|
|
}
|
|
|
|
if (firing_an_ak && p_person->Genus.Person->Timer1 < fire_length)
|
|
{
|
|
SLONG old_timer = p_person->Genus.Person->Timer1;
|
|
|
|
set_person_shoot(p_person, TRUE);
|
|
|
|
p_person->Genus.Person->Timer1 = old_timer + 1;
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
/*
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
Thing *p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
//
|
|
// Using a special.
|
|
//
|
|
|
|
|
|
if (p_special->Genus.Special->SpecialType == SPECIAL_AK47)
|
|
{
|
|
p_person->Genus.Person->Timer1+=TICK_TOCK;
|
|
if(p_person->Genus.Person->Timer1>200) // 1/5th of a second
|
|
if(continue_firing(p_person))
|
|
{
|
|
p_person->Genus.Person->Timer1=0; // 1/5th of a second
|
|
|
|
set_person_shoot(p_person, TRUE);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
set_person_aim(p_person);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_GUN_AWAY:
|
|
break;
|
|
case SUB_STATE_STOPPING:
|
|
p_person->SubState=SUB_STATE_AIM_GUN;
|
|
p_person->Genus.Person->Action=ACTION_AIM_GUN;
|
|
break;
|
|
|
|
case SUB_STATE_DRAW_ITEM:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (p_person->Draw.Tweened->FrameIndex == 3 &&
|
|
p_person->Genus.Person->SpecialDraw &&
|
|
p_person->Genus.Person->SpecialUse != p_person->Genus.Person->SpecialDraw)
|
|
{
|
|
//
|
|
// Use the special we are drawing.
|
|
//
|
|
|
|
if (!person_has_special(p_person, p_person->Genus.Person->SpecialDraw))
|
|
|
|
p_person->Genus.Person->SpecialUse = p_person->Genus.Person->SpecialDraw;
|
|
|
|
//
|
|
// Draw the special in this person's hand.
|
|
//
|
|
|
|
set_persons_personid(p_person);
|
|
}
|
|
|
|
if (end == 1)
|
|
{
|
|
if(p_person->Genus.Person->PlayerID && continue_moveing(p_person))
|
|
{
|
|
set_person_running(p_person);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
SLONG anim;
|
|
Thing *p_special;
|
|
|
|
if (p_person->Genus.Person->SpecialUse == 0)
|
|
{
|
|
//
|
|
// Gun might have been knocked out of hand while
|
|
// drawing it...
|
|
//
|
|
|
|
set_person_idle(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
ASSERT(p_person->Genus.Person->SpecialUse);
|
|
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
switch(p_special->Genus.Special->SpecialType)
|
|
{
|
|
case SPECIAL_GUN:
|
|
anim=ANIM_PISTOL_AIM_AHEAD;
|
|
break;
|
|
case SPECIAL_SHOTGUN:
|
|
anim = ANIM_SHOTGUN_AIM;
|
|
break;
|
|
case SPECIAL_AK47:
|
|
// if (p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
// anim = ANIM_AK_AIM;
|
|
// else
|
|
anim = ANIM_SHOTGUN_AIM;
|
|
break;
|
|
default:
|
|
set_person_idle(p_person);
|
|
return;
|
|
}
|
|
p_person->SubState=SUB_STATE_AIM_GUN;
|
|
set_anim(p_person,anim);
|
|
p_person->Genus.Person->Action=ACTION_AIM_GUN;
|
|
p_person->Genus.Person->Flags &= ~(FLAG_PERSON_NON_INT_C | FLAG_PERSON_NON_INT_M);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_ITEM_AWAY:
|
|
p_person->Genus.Person->SpecialUse = NULL;
|
|
set_persons_personid(p_person);
|
|
set_person_idle(p_person);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
#define COMBO_ACCURACY 300 // Was 190
|
|
|
|
SLONG person_new_combat_node(Thing *p_person)
|
|
{
|
|
SBYTE node=0;
|
|
UBYTE new_node=0;
|
|
UWORD anim;
|
|
MSG_add(" new node y %d \n",p_person->WorldPos.Y>>8);
|
|
|
|
node=p_person->Genus.Person->CombatNode;
|
|
|
|
if(node>0)
|
|
if(get_combat_type_for_node(node)!=COMBAT_NONE)
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
if(p_person->Genus.Person->pcom_ai_counter>COMBO_ACCURACY)
|
|
{
|
|
//
|
|
// don't continue combo
|
|
//
|
|
p_person->Genus.Person->CombatNode=-p_person->Genus.Person->CombatNode;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_REQUEST_KICK|FLAG_PERSON_REQUEST_PUNCH);
|
|
#ifndef PSX
|
|
|
|
{
|
|
// CBYTE str[100];
|
|
// sprintf(str,"MISS TIMED COMBO %d GT %d",p_person->Genus.Person->pcom_ai_counter,COMBO_ACCURACY);
|
|
// CONSOLE_text(str);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
p_person->Genus.Person->pcom_ai_counter=0;
|
|
|
|
}
|
|
|
|
if(node)
|
|
{
|
|
if(node>0)
|
|
{
|
|
if(!p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// non players must now decide wether to continue the combo
|
|
//
|
|
|
|
if((Random()&255)<GET_SKILL(p_person)*10)
|
|
{
|
|
switch(node)
|
|
{
|
|
case 1:
|
|
case 3:
|
|
case 5:
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_REQUEST_PUNCH;
|
|
break;
|
|
case 6:
|
|
case 8:
|
|
case 9:
|
|
p_person->Genus.Person->Flags|=FLAG_PERSON_REQUEST_KICK;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if((p_person->Genus.Person->Flags&(FLAG_PERSON_REQUEST_PUNCH|FLAG_PERSON_REQUEST_KICK)) && node>0)
|
|
{
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_REQUEST_PUNCH) //punch
|
|
{
|
|
new_node=get_anim_and_node_for_action(node,2,&anim);
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_PUNCH;
|
|
}
|
|
|
|
if(!new_node)
|
|
{
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_REQUEST_KICK) //kick
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_KICK;
|
|
new_node=get_anim_and_node_for_action(node,4,&anim);
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// if node is negative then we missed so can't continue the combo
|
|
//
|
|
new_node=get_anim_and_node_for_action(abs(node),1,&anim); //finished
|
|
}
|
|
|
|
|
|
if(new_node&&anim)
|
|
{
|
|
p_person->Genus.Person->CombatNode=new_node;
|
|
queue_anim(p_person,anim);
|
|
person_normal_animate(p_person); // to get the queued anim into the nextframe field
|
|
MSG_add(" new node && anim y %d \n",p_person->WorldPos.Y>>8);
|
|
return(1);
|
|
}
|
|
|
|
}
|
|
return(0);
|
|
}
|
|
extern SLONG should_i_block(Thing *p_person,Thing *p_agressor,SLONG anim);
|
|
|
|
void aim_at_victim(Thing *p_person,SLONG count)
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim!=ANIM_KICK_COMBO3b)
|
|
if(p_person->Draw.Tweened->CurrentAnim!=ANIM_FIGHT_STOMP)
|
|
if(p_person->Genus.Person->Target)
|
|
{
|
|
Thing *p_target;
|
|
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
|
|
if(count_gang(p_person)<=count)
|
|
{
|
|
turn_to_face_thing(p_person,p_target,0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
UBYTE combo_display=0;
|
|
void fn_person_fighting(Thing *p_person)
|
|
{
|
|
Thing *p_target;
|
|
SLONG end=0;
|
|
//return;
|
|
// MSG_add(" fighting substate %d action %d",p_person->SubState,p_person->Genus.Person->Action);
|
|
|
|
SlideSoundCheck(p_person);
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_WALL_KICK:
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
//MSG_add(" finish punch");
|
|
p_person->Draw.Tweened->Angle+=1024;
|
|
p_person->Draw.Tweened->Angle&=2047;
|
|
|
|
set_person_fight_idle(p_person);
|
|
}
|
|
break;
|
|
|
|
case SUB_STATE_BLOCK:
|
|
|
|
|
|
if(p_person->Draw.Tweened->FrameIndex==2)
|
|
{
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_REQUEST_KICK)
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_KICK;
|
|
set_person_leg_sweep(p_person);
|
|
return;
|
|
|
|
}
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
extern SLONG continue_blocking(Thing *p_person);
|
|
if(continue_blocking(p_person))
|
|
{
|
|
goto skip_animate;
|
|
}
|
|
|
|
}
|
|
}
|
|
end = person_normal_animate(p_person);
|
|
skip_animate:
|
|
if (end==1)
|
|
{
|
|
{
|
|
set_person_fight_idle(p_person);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_PUNCH:
|
|
// person_normal_move(p_person);
|
|
//MSG_add(" do punch");
|
|
Thing *p_target;
|
|
if(p_person->Genus.Person->Target)
|
|
{
|
|
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
aim_at_victim(p_person);
|
|
/*
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
|
|
if(count_gang(p_person)<=1)
|
|
{
|
|
turn_to_face_thing(p_person,TO_THING(p_person->Genus.Person->Target),0);
|
|
}
|
|
}
|
|
*/
|
|
/*
|
|
if(count_gang(p_person)<=1)
|
|
{
|
|
turn_to_face_thing(p_person,TO_THING(p_person->Genus.Person->Target),0);
|
|
}
|
|
*/
|
|
|
|
if(p_target->Class==CLASS_PERSON)
|
|
if(p_target->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// punch player , so check over and over if they want to block
|
|
//
|
|
|
|
if(should_i_block(p_target,p_person,0))
|
|
p_target->Genus.Person->Flags|=FLAG_PERSON_REQUEST_BLOCK;
|
|
|
|
}
|
|
}
|
|
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_PUNCH_COMBO2:
|
|
//case ANIM_PUNCH_COMBO3:
|
|
if(p_person->Draw.Tweened->FrameIndex<2)
|
|
{
|
|
p_person->Velocity=6;
|
|
person_normal_move(p_person);
|
|
}
|
|
|
|
break;
|
|
}
|
|
if(p_person->Genus.Person->Flags&(FLAG_PERSON_REQUEST_PUNCH|FLAG_PERSON_REQUEST_KICK))
|
|
{
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
p_person->Genus.Person->pcom_ai_counter+=TICK_TOCK;
|
|
}
|
|
|
|
}
|
|
end=person_normal_animate(p_person);
|
|
|
|
if(0)
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
SLONG index1=0,index2;
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_PUNCH_COMBO1:
|
|
index1=3;
|
|
index2=4;
|
|
break;
|
|
case ANIM_PUNCH_COMBO2:
|
|
index1=3;
|
|
index2=4;
|
|
break;
|
|
// case ANIM_PUNCH_COMBO3:
|
|
// index=4;
|
|
// break;
|
|
}
|
|
|
|
if(index1)
|
|
if(p_person->Draw.Tweened->FrameIndex>=index1&&p_person->Draw.Tweened->FrameIndex<=index2)
|
|
{
|
|
combo_display=1;
|
|
}
|
|
}
|
|
if(end==1)
|
|
{
|
|
if(person_new_combat_node(p_person))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
MSG_add(" finish punch");
|
|
set_person_fight_idle(p_person);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_KICK:
|
|
// change_velocity_to(p_person,16);
|
|
// person_normal_move(p_person);
|
|
|
|
if(p_person->Genus.Person->Target)
|
|
{
|
|
aim_at_victim(p_person);
|
|
/*
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
|
|
if(count_gang(p_person)<=1)
|
|
{
|
|
turn_to_face_thing(p_person,TO_THING(p_person->Genus.Person->Target),0);
|
|
}
|
|
}
|
|
*/
|
|
/*
|
|
if(count_gang(p_person)<=1)
|
|
{
|
|
turn_to_face_thing(p_person,TO_THING(p_person->Genus.Person->Target),0);
|
|
}
|
|
*/
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
if(p_target->Class==CLASS_PERSON)
|
|
if(p_target->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// punch player , so check over and over if they want to block
|
|
//
|
|
|
|
if(should_i_block(p_target,p_person,0))
|
|
p_target->Genus.Person->Flags|=FLAG_PERSON_REQUEST_BLOCK;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if(p_person->Genus.Person->Flags&(FLAG_PERSON_REQUEST_KICK|FLAG_PERSON_REQUEST_PUNCH))
|
|
{
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
p_person->Genus.Person->pcom_ai_counter+=TICK_TOCK;
|
|
}
|
|
|
|
}
|
|
end=person_normal_animate(p_person);
|
|
|
|
if(0)
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
SLONG index1=0,index2;
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_KICK_COMBO1:
|
|
index1=3;
|
|
index2=4;
|
|
break;
|
|
case ANIM_KICK_COMBO2:
|
|
index1=1;
|
|
index2=4;
|
|
break;
|
|
}
|
|
|
|
if(index1)
|
|
if(p_person->Draw.Tweened->FrameIndex>=index1&&p_person->Draw.Tweened->FrameIndex<=index2)
|
|
{
|
|
combo_display=2;
|
|
}
|
|
}
|
|
|
|
if(end==1)
|
|
{
|
|
if(person_new_combat_node(p_person))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
set_person_fight_idle(p_person);
|
|
}
|
|
}
|
|
break;
|
|
case SUB_STATE_STRANGLE:
|
|
case SUB_STATE_HEADBUTT:
|
|
|
|
{
|
|
static UBYTE last_frame = 0;
|
|
|
|
end=person_normal_animate_speed(p_person,256);
|
|
|
|
if (last_frame != p_person->Draw.Tweened->FrameIndex)
|
|
{
|
|
last_frame = p_person->Draw.Tweened->FrameIndex;
|
|
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
ASSERT(p_target->Class == CLASS_PERSON);
|
|
|
|
//PANEL_new_text(NULL, 400, "Frame = %d", last_frame);
|
|
|
|
//
|
|
// Damage our victim.
|
|
//
|
|
|
|
if ((p_target->Genus.Person->pcom_bent & PCOM_BENT_PLAYERKILL) && !p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// Only the player can hurt this person
|
|
//
|
|
}
|
|
else
|
|
if (p_target->Genus.Person->Flags2 & FLAG2_PERSON_INVULNERABLE)
|
|
{
|
|
//
|
|
// Nothing hurts this person.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
if (p_person->SubState == SUB_STATE_STRANGLE)
|
|
{
|
|
if (last_frame == 27 || ((last_frame & 1) == 0 && last_frame >= 14 && last_frame <= 24))
|
|
{
|
|
SLONG damage;
|
|
|
|
//
|
|
// A strangulation frame.
|
|
//
|
|
|
|
damage = 40 - GET_SKILL(p_target) >> 3;
|
|
damage += 1;
|
|
|
|
p_target->Genus.Person->Health -= damage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (last_frame == 11)
|
|
{
|
|
//
|
|
// This is the headbutting frame!
|
|
//
|
|
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
SWORD hit_wave;
|
|
|
|
ASSERT(p_target->Class == CLASS_PERSON);
|
|
|
|
p_target->Genus.Person->Health -= 40 - GET_SKILL(p_target);
|
|
|
|
if (SOUND_Gender(p_target)==1)
|
|
hit_wave = SOUND_Range(S_BAT_MALE_START,S_BAT_MALE_END);
|
|
else
|
|
hit_wave = SOUND_Range(S_BAT_FEMALE_START,S_BAT_FEMALE_END);
|
|
MFX_play_thing(THING_NUMBER(p_target),hit_wave,0,p_target);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(end)
|
|
{
|
|
set_person_fight_idle(p_person);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_HEADBUTTV:
|
|
case SUB_STATE_STRANGLEV:
|
|
|
|
end=person_normal_animate_speed(p_person,256);
|
|
|
|
if(end)
|
|
{
|
|
if (p_person->Genus.Person->Health <= 0)
|
|
{
|
|
//
|
|
// This person is dead- make him die using the same
|
|
// bit of code that everyone else uses.
|
|
//
|
|
|
|
remove_from_gang_attack(p_person,TO_THING(p_person->Genus.Person->Target));
|
|
|
|
set_generic_person_state_function(p_person, STATE_DYING);
|
|
|
|
p_person->SubState = SUB_STATE_DYING_ACTUALLY_DIE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This person is alive.
|
|
//
|
|
|
|
set_person_dead(
|
|
p_person,
|
|
0,
|
|
PERSON_DEATH_TYPE_STAY_ALIVE_PRONE,
|
|
0,
|
|
0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case SUB_STATE_GRAPPLE:
|
|
end=person_normal_animate_speed(p_person,256);
|
|
if((p_person->Draw.Tweened->FrameIndex==8)&&(p_person->Draw.Tweened->CurrentAnim==ANIM_NECK_SNAP))
|
|
// play_quick_wave(p_person,S_NECK_BREAK,WAVE_PLAY_NO_INTERUPT);
|
|
MFX_play_thing(THING_NUMBER(p_person),S_NECK_BREAK,0,p_person);
|
|
|
|
if(end==1)
|
|
{
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_GRAB_ARM:
|
|
case ANIM_GRAB_ARM_KNEE1:
|
|
p_person->SubState=SUB_STATE_GRAPPLE_HOLD;
|
|
break;
|
|
default:
|
|
set_person_fight_idle(p_person);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_GRAPPLEE:
|
|
if ( (p_person->Draw.Tweened->CurrentAnim==ANIM_PISTOL_WHIP_TAKE)
|
|
&&(MagicFrameCheck(p_person,4))
|
|
)
|
|
MFX_play_thing(THING_NUMBER(p_person),S_JUDO_CHOP,0,p_person);
|
|
end=person_normal_animate_speed(p_person,256);
|
|
if(end==1)
|
|
{
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_GRAB_ARMV:
|
|
p_person->SubState=SUB_STATE_GRAPPLE_HELD;
|
|
break;
|
|
case ANIM_PISTOL_WHIP_TAKE:
|
|
set_person_dead(p_person,TO_THING(p_person->Genus.Person->Target),PERSON_DEATH_TYPE_STAY_ALIVE_PRONE,0,0);
|
|
break;
|
|
default:
|
|
//
|
|
// knee to death
|
|
//
|
|
// ASSERT(0);
|
|
// kneck snap
|
|
/*
|
|
if(p_person->Genus.Person->Target)
|
|
{
|
|
remove_from_gang_attack(p_person,TO_THING(p_person->Genus.Person->Target));
|
|
}
|
|
|
|
set_generic_person_state_function(p_person,STATE_DEAD);
|
|
p_person->Genus.Person->Action = ACTION_DEAD;
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
p_person->SubState=0;
|
|
*/
|
|
set_person_dead(p_person,TO_THING(p_person->Genus.Person->Target),PERSON_DEATH_TYPE_PRONE,0,0);
|
|
break;
|
|
|
|
}
|
|
}
|
|
break;
|
|
case SUB_STATE_GRAPPLE_ATTACK:
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_GRAB_ARM_THROW: //victim dead
|
|
case ANIM_GRAB_ARM_KNEE2: //victim dead
|
|
set_person_fight_idle(p_person);
|
|
break;
|
|
default:
|
|
p_person->SubState=SUB_STATE_GRAPPLE_HOLD;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// nobodys escaping during the attack
|
|
//
|
|
//TO_THING(p_person->Genus.Person->Target)->Genus.Person->Escape=0;
|
|
}
|
|
break;
|
|
|
|
case SUB_STATE_GRAPPLE_HOLD:
|
|
|
|
{
|
|
ASSERT(p_person->Genus.Person->Target);
|
|
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
ASSERT(p_target->Class == CLASS_PERSON);
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
track_enemy(TO_THING(p_person->Genus.Person->Target));
|
|
}
|
|
|
|
if (p_person->Genus.Person->Flags&FLAG_PERSON_REQUEST_KICK)
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_KICK;
|
|
|
|
if ((p_target->Genus.Person->pcom_bent & PCOM_BENT_PLAYERKILL) && !p_person->Genus.Person->PlayerID)
|
|
{
|
|
//
|
|
// Only the player can hurt this person.
|
|
//
|
|
}
|
|
else
|
|
if (p_target->Genus.Person->pcom_ai == PCOM_AI_FIGHT_TEST && (p_target->Genus.Person->pcom_ai_other & PCOM_COMBAT_GRAPPLE_ATTACK))
|
|
{
|
|
//
|
|
// This fight test dummy dies through a grapple attack- even when marked
|
|
// as invulnerable.
|
|
//
|
|
|
|
p_target->Genus.Person->Health = 0;
|
|
}
|
|
else
|
|
if (p_target->Genus.Person->Flags2 & FLAG2_PERSON_INVULNERABLE)
|
|
{
|
|
//
|
|
// Nothing hurts this person.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
p_target->Genus.Person->Health -= 45 - GET_SKILL(p_target) >> 1;
|
|
#ifdef PSX
|
|
if (p_target->Genus.Person->PlayerID)
|
|
PSX_SetShock(0,128);
|
|
#endif
|
|
#ifdef TARGET_DC
|
|
if (p_target->Genus.Person->PlayerID)
|
|
{
|
|
Vibrate ( 20.0f, 1.0f, 0.25f );
|
|
}
|
|
#endif
|
|
// add_damage_value_thing(p_person,20>>1);
|
|
}
|
|
|
|
if (p_target->Genus.Person->Health<=0)
|
|
{
|
|
p_target->Genus.Person->Health=0;
|
|
set_anim(p_person,ANIM_GRAB_ARM_KNEE2);
|
|
set_anim(p_target,ANIM_GRAB_ARM_KNEE2V);
|
|
|
|
if (p_person)
|
|
{
|
|
p_person->Genus.Person->Flags2 |= FLAG2_PERSON_IS_MURDERER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
set_anim(p_person,ANIM_GRAB_ARM_KNEE1);
|
|
set_anim(p_target,ANIM_GRAB_ARM_KNEE1V);
|
|
}
|
|
p_person->SubState=SUB_STATE_GRAPPLE_ATTACK;
|
|
|
|
}
|
|
else
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_REQUEST_PUNCH)
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_PUNCH;
|
|
set_anim(p_person,ANIM_GRAB_ARM_THROW);
|
|
set_anim(TO_THING(p_person->Genus.Person->Target),ANIM_GRAB_ARM_THROWV);
|
|
// TO_THING(p_person->Genus.Person->Target)->Genus.Person->Escape=0;
|
|
|
|
p_person->SubState=SUB_STATE_GRAPPLE_ATTACK;
|
|
}
|
|
}
|
|
|
|
|
|
break;
|
|
case SUB_STATE_GRAPPLE_HELD:
|
|
|
|
{
|
|
Thing *p_attacker = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
if((p_person->Genus.Person->Flags&(FLAG_PERSON_REQUEST_BLOCK|FLAG_PERSON_REQUEST_KICK|FLAG_PERSON_REQUEST_PUNCH)) || (PTIME(p_person)&3)==0)
|
|
{
|
|
/*
|
|
#ifndef PSX
|
|
CBYTE str[100];
|
|
sprintf(str," press c on turn %d escape %d\n",GAME_TURN,p_person->Genus.Person->Escape);
|
|
CONSOLE_text(str,8000);
|
|
#endif
|
|
*/
|
|
p_person->Genus.Person->Escape++;
|
|
// p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_BLOCK;
|
|
p_person->Genus.Person->Flags&=~(FLAG_PERSON_REQUEST_BLOCK|FLAG_PERSON_REQUEST_KICK|FLAG_PERSON_REQUEST_PUNCH);
|
|
}
|
|
|
|
if (p_attacker->SubState!=SUB_STATE_GRAPPLE_ATTACK)
|
|
{
|
|
SLONG escape_count = 23;
|
|
|
|
if(p_person->Genus.Person->PlayerID)
|
|
{
|
|
escape_count = 15;
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_FIGHT_TEST && !(p_person->Genus.Person->pcom_ai_other & PCOM_COMBAT_GRAPPLE_ATTACK))
|
|
{
|
|
escape_count = 0;
|
|
}
|
|
else
|
|
{
|
|
escape_count-=(GET_SKILL(p_person)>>1);
|
|
|
|
// escape_count=10000; //for debugging grapple
|
|
}
|
|
|
|
if (p_attacker->SubState != SUB_STATE_GRAPPLE &&
|
|
p_attacker->SubState != SUB_STATE_GRAPPLE_HOLD &&
|
|
p_attacker->SubState != SUB_STATE_GRAPPLE_ATTACK)
|
|
{
|
|
//
|
|
// Our attacker is no longer holding us...
|
|
//
|
|
|
|
p_person->Genus.Person->Escape=0;
|
|
p_person->SubState=SUB_STATE_ESCAPE;
|
|
set_anim(p_person,ANIM_GRAB_ARM_ESCAPEV);
|
|
|
|
return;
|
|
}
|
|
else
|
|
if (p_person->Genus.Person->Escape > escape_count)
|
|
{
|
|
p_person->Genus.Person->Escape=0;
|
|
set_anim(p_person,ANIM_GRAB_ARM_ESCAPEV);
|
|
p_person->SubState=SUB_STATE_ESCAPE;
|
|
set_anim(p_attacker,ANIM_GRAB_ARM_ESCAPE);
|
|
p_attacker->SubState=SUB_STATE_ESCAPE;
|
|
return;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
end=person_normal_animate(p_person);
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
|
|
case ANIM_GRAB_ARM_THROWV:
|
|
|
|
if (end)
|
|
{
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_FIGHT_TEST && (p_person->Genus.Person->pcom_ai_other & PCOM_COMBAT_GRAPPLE_ATTACK))
|
|
{
|
|
//
|
|
// This fight test dummy dies through a grapple attack- even when marked
|
|
// as invulnerable.
|
|
//
|
|
|
|
p_person->Genus.Person->Health = 0;
|
|
|
|
set_person_dead(p_person,TO_THING(p_person->Genus.Person->Target),PERSON_DEATH_TYPE_PRONE,0,0);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just knocked out.
|
|
//
|
|
|
|
set_person_dead(p_person,TO_THING(p_person->Genus.Person->Target),PERSON_DEATH_TYPE_STAY_ALIVE_PRONE,0,0);
|
|
}
|
|
}
|
|
|
|
if (MagicFrameCheck(p_person,8)) {
|
|
// if (p_person->Genus.Person->PersonType==PERSON_DARCI)
|
|
if (SOUND_Gender(p_person)==2)
|
|
MFX_play_thing(THING_NUMBER(p_person),S_FEMALE_DIE_2,0,p_person);
|
|
else
|
|
MFX_play_thing(THING_NUMBER(p_person),S_MALE_DIE_2,0,p_person);
|
|
}
|
|
|
|
break;
|
|
case ANIM_GRAB_ARM_KNEE1V:
|
|
if (MagicFrameCheck(p_person,2)) {
|
|
MFX_play_thing(THING_NUMBER(p_person),S_PUNCH_START+(GAME_TURN&3),0,p_person);
|
|
PainSound(p_person);
|
|
}
|
|
break;
|
|
case ANIM_GRAB_ARM_KNEE2V:
|
|
if (MagicFrameCheck(p_person,2)) {
|
|
MFX_play_thing(THING_NUMBER(p_person),S_PUNCH_START+(GAME_TURN&3),0,p_person);
|
|
PainSound(p_person);
|
|
}
|
|
if(end)
|
|
{
|
|
// ASSERT(0);
|
|
set_person_dead(p_person,TO_THING(p_person->Genus.Person->Target),PERSON_DEATH_TYPE_PRONE,0,0);
|
|
/*
|
|
if(p_person->Genus.Person->Target)
|
|
{
|
|
remove_from_gang_attack(p_person,TO_THING(p_person->Genus.Person->Target));
|
|
}
|
|
|
|
set_generic_person_state_function(p_person,STATE_DEAD);
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
p_person->Genus.Person->Action = ACTION_DEAD;
|
|
p_person->SubState=0;
|
|
*/
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
break;
|
|
case SUB_STATE_ESCAPE:
|
|
end=person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
set_person_idle(p_person);
|
|
if(!p_person->Genus.Person->PlayerID)
|
|
{
|
|
PCOM_attack_happened(p_person,TO_THING(p_person->Genus.Person->Target));
|
|
}
|
|
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_HELPLESS;
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case SUB_STATE_STEP:
|
|
end=person_normal_animate(p_person);
|
|
plant_feet(p_person); //gasp
|
|
if(p_person->State==STATE_DANGLING)
|
|
return;
|
|
|
|
if(end==1)
|
|
{
|
|
// set_person_locked_idle_ready(p_person);
|
|
set_person_fight_idle(p_person);
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_STEP_FORWARD:
|
|
|
|
|
|
p_person->Genus.Person->Timer1++;
|
|
if(p_person->Genus.Person->Flags&FLAG_PERSON_REQUEST_BLOCK)
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim==ANIM_FIGHT_STEP_S)
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_BLOCK;
|
|
set_person_block(p_person);
|
|
return;
|
|
}
|
|
}
|
|
// change_velocity_to(p_person,30);
|
|
// p_person->Velocity=(p_person->Genus.Person->AnimType==ANIM_TYPE_ROPER) ? 15 : 30; //15:30
|
|
p_person->Velocity= 30; //15:30
|
|
if(p_person->Draw.Tweened->FrameIndex<2)
|
|
{
|
|
SLONG old_angle;
|
|
old_angle=p_person->Draw.Tweened->Angle;
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_FIGHT_STEP_N:
|
|
case ANIM_FIGHT_STEP_N_BAT:
|
|
break;
|
|
case ANIM_FIGHT_STEP_E:
|
|
case ANIM_FIGHT_STEP_E_BAT:
|
|
p_person->Draw.Tweened->Angle=(p_person->Draw.Tweened->Angle-512)&2047;
|
|
|
|
break;
|
|
case ANIM_FIGHT_STEP_W:
|
|
case ANIM_FIGHT_STEP_W_BAT:
|
|
p_person->Draw.Tweened->Angle=(p_person->Draw.Tweened->Angle+512)&2047;
|
|
break;
|
|
case ANIM_FIGHT_STEP_S:
|
|
case ANIM_FIGHT_STEP_S_BAT:
|
|
p_person->Draw.Tweened->Angle=(p_person->Draw.Tweened->Angle+1024)&2047;
|
|
break;
|
|
}
|
|
person_normal_move(p_person);
|
|
p_person->Draw.Tweened->Angle=old_angle;
|
|
}
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_FIGHT_STEP_N:
|
|
case ANIM_FIGHT_STEP_N_BAT:
|
|
case ANIM_FIGHT_STEP_S:
|
|
case ANIM_FIGHT_STEP_S_BAT:
|
|
aim_at_victim(p_person,1000);
|
|
break;
|
|
default:
|
|
aim_at_victim(p_person,1);
|
|
break;
|
|
|
|
}
|
|
end=person_normal_animate(p_person);
|
|
|
|
if(end)
|
|
{
|
|
reset_gang_attack(p_person);
|
|
|
|
set_person_fight_idle(p_person);
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
MSG_add("FIGHTING unknow substate %d \n",p_person->SubState);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void fn_person_wait(Thing *p_person)
|
|
{
|
|
/*
|
|
|
|
struct Command *com;
|
|
SLONG end;
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
|
|
}
|
|
com=TO_COMMAND(p_person->Genus.Person->Command);
|
|
|
|
switch(com->CommandType)
|
|
{
|
|
case COM_WAIT_FOR_TRIGGER:
|
|
if(TO_THING(com->Data1)->Genus.Switch->Flags&SWITCH_FLAGS_TRIGGERED)
|
|
{
|
|
advance_person_command(p_person);
|
|
|
|
}
|
|
break;
|
|
case COM_WAIT_FOR_CLIST:
|
|
if(TO_CONLIST(com->Data1)->Flags&LIST_TRUE)
|
|
{
|
|
advance_person_command(p_person);
|
|
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Genus.Person->AnimType==4)
|
|
if((GAME_TURN&0x3f)==0)
|
|
{
|
|
queue_anim(p_person,ANIM_DESPAIR);
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
SLONG turn_to_face_thing(Thing *p_person,Thing *p_target,SLONG slow)
|
|
{
|
|
SLONG dx,dz;
|
|
SLONG angle,pangle;
|
|
SLONG angle_diff;
|
|
SLONG dist;
|
|
SLONG ax,ay,az,bx,by,bz;
|
|
|
|
ASSERT(p_person->Genus.Person->Target);
|
|
if(p_target->Class!=CLASS_PERSON)
|
|
return(200);
|
|
ASSERT(p_target->Class==CLASS_PERSON);
|
|
ASSERT(p_target->Draw.Tweened);
|
|
|
|
// p_target=TO_THING(p_person->Genus.Person->Target);
|
|
|
|
// e_draw_3d_line(p_person->WorldPos.X,0,p_person->WorldPos.Z,p_target->WorldPos.X,0,p_target->WorldPos.Z);
|
|
calc_sub_objects_position(p_person,p_person->Draw.Tweened->AnimTween,SUB_OBJECT_PELVIS,&ax,&ay,&az);
|
|
ax+=p_person->WorldPos.X>>8;
|
|
ay+=p_person->WorldPos.Y>>8;
|
|
az+=p_person->WorldPos.Z>>8;
|
|
calc_sub_objects_position(p_target,p_target->Draw.Tweened->AnimTween,SUB_OBJECT_PELVIS,&bx,&by,&bz);
|
|
bx+=p_target->WorldPos.X>>8;
|
|
by+=p_target->WorldPos.Y>>8;
|
|
bz+=p_target->WorldPos.Z>>8;
|
|
|
|
dx=bx-ax; //(p_target->WorldPos.X-p_person->WorldPos.X)>>8;
|
|
dz=bz-az;//(p_target->WorldPos.Z-p_person->WorldPos.Z)>>8;
|
|
|
|
dist=QDIST2(abs(dx),abs(dz));
|
|
|
|
if (dist > 0x30)
|
|
{
|
|
angle = (Arctan(dx,-dz)+1024+2048)&2047;
|
|
// MSG_add(" cop turn to reqd %d ",angle);
|
|
|
|
pangle = p_person->Draw.Tweened->Angle;
|
|
angle_diff=angle-pangle;
|
|
|
|
if(angle_diff>1024)
|
|
angle_diff-=2048;
|
|
if(angle_diff<-1024)
|
|
angle_diff+=2048;
|
|
|
|
angle_diff>>=slow;
|
|
|
|
angle=(pangle+angle_diff+2048)&2047;
|
|
|
|
p_person->Draw.Tweened->Angle=angle;
|
|
}
|
|
|
|
return(dist);
|
|
}
|
|
|
|
void turn_to_face_thing_quick(Thing *p_person,Thing *p_target)
|
|
{
|
|
SLONG dx,dz;
|
|
SLONG angle,pangle;
|
|
SLONG angle_diff;
|
|
SLONG dist;
|
|
SLONG ax,ay,az,bx,by,bz;
|
|
|
|
// ASSERT(p_person->Genus.Person->Target);
|
|
ASSERT(p_target->Class==CLASS_PERSON);
|
|
ASSERT(p_target->Draw.Tweened);
|
|
ax=p_person->WorldPos.X>>8;
|
|
ay=p_person->WorldPos.Y>>8;
|
|
az=p_person->WorldPos.Z>>8;
|
|
|
|
bx=p_target->WorldPos.X>>8;
|
|
by=p_target->WorldPos.Y>>8;
|
|
bz=p_target->WorldPos.Z>>8;
|
|
|
|
dx=bx-ax; //(p_target->WorldPos.X-p_person->WorldPos.X)>>8;
|
|
dz=bz-az;//(p_target->WorldPos.Z-p_person->WorldPos.Z)>>8;
|
|
dist=QDIST2(abs(dx),abs(dz));
|
|
|
|
if (dist > 0x30)
|
|
{
|
|
angle = (Arctan(dx,-dz)+1024+2048)&2047;
|
|
|
|
|
|
p_person->Draw.Tweened->Angle=angle;
|
|
}
|
|
|
|
}
|
|
|
|
SLONG get_pitch_to_thing_quick(Thing *p_person,Thing *p_target)
|
|
{
|
|
SLONG dx,dy,dz,dxz;
|
|
SLONG angle,pangle;
|
|
SLONG angle_diff;
|
|
SLONG dist;
|
|
SLONG ax,ay,az,bx,by,bz;
|
|
|
|
// ASSERT(p_person->Genus.Person->Target);
|
|
ASSERT(p_target->Class==CLASS_PERSON);
|
|
ASSERT(p_target->Draw.Tweened);
|
|
ax=p_person->WorldPos.X>>8;
|
|
ay=p_person->WorldPos.Y>>8;
|
|
az=p_person->WorldPos.Z>>8;
|
|
|
|
bx=p_target->WorldPos.X>>8;
|
|
by=p_target->WorldPos.Y>>8;
|
|
bz=p_target->WorldPos.Z>>8;
|
|
|
|
dx=abs(bx-ax); //(p_target->WorldPos.X-p_person->WorldPos.X)>>8;
|
|
dy=(by-ay); //(p_target->WorldPos.X-p_person->WorldPos.X)>>8;
|
|
dz=abs(bz-az);//(p_target->WorldPos.Z-p_person->WorldPos.Z)>>8;
|
|
|
|
dxz=QDIST2(dx,dz);
|
|
|
|
angle = Arctan(dy,dxz);
|
|
|
|
return(angle&2047);
|
|
}
|
|
|
|
void set_person_draw_item(Thing *p_person, SLONG special_type)
|
|
{
|
|
SLONG anim;
|
|
Thing *p_special;
|
|
|
|
if(p_person->Genus.Person->Flags2 & FLAG2_PERSON_CARRYING)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Does this person have an item of that type?
|
|
//
|
|
|
|
p_special = person_has_special(p_person, special_type);
|
|
|
|
if (p_special == NULL)
|
|
{
|
|
//
|
|
// The person cannot draw an item if it doesn't have it!
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// clear old weapon
|
|
//
|
|
p_person->Genus.Person->SpecialUse = 0;
|
|
p_person->Draw.Tweened->PersonID &= 0x1f;
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_GUN_OUT;
|
|
|
|
|
|
set_persons_personid(p_person);
|
|
|
|
//
|
|
// Which animation shall we use?
|
|
//
|
|
|
|
anim = ANIM_PISTOL_DRAW;
|
|
/*
|
|
if (special_type == SPECIAL_SHOTGUN ||
|
|
special_type == SPECIAL_AK47)
|
|
{
|
|
//
|
|
// These are two-handed weapons- so use a different animation.
|
|
//
|
|
|
|
anim = ANIM_SHOTGUN_DRAW;
|
|
}*/
|
|
switch (special_type)
|
|
{
|
|
case SPECIAL_SHOTGUN:
|
|
anim = ANIM_SHOTGUN_DRAW;
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
break;
|
|
case SPECIAL_KNIFE:
|
|
anim = ANIM_KNIFE_DRAW;
|
|
break;
|
|
case SPECIAL_BASEBALLBAT:
|
|
anim = ANIM_BAT_DRAW;
|
|
break;
|
|
case SPECIAL_AK47:
|
|
p_person->Genus.Person->Mode = PERSON_MODE_RUN;
|
|
// if (p_person->Genus.Person->PersonType==PERSON_ROPER)
|
|
// anim = ANIM_AK_DRAW;
|
|
// else
|
|
anim = ANIM_SHOTGUN_DRAW;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Stand still and do the draw item anim.
|
|
//
|
|
|
|
set_anim (p_person, anim);
|
|
set_thing_velocity (p_person, 0);
|
|
set_generic_person_state_function(p_person, STATE_GUN);
|
|
|
|
p_person->SubState = SUB_STATE_DRAW_ITEM;
|
|
p_person->Genus.Person->SpecialDraw = THING_NUMBER(p_special);
|
|
p_person->Genus.Person->Action = ACTION_DRAW_SPECIAL;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NON_INT_C | FLAG_PERSON_NON_INT_M;
|
|
// p_person->Genus.Person->Flags |= FLAG_PERSON_LOCK_ANIM_CHANGE;
|
|
}
|
|
|
|
void set_person_item_away(Thing *p_person)
|
|
{
|
|
//
|
|
// No anim for putting away an item?
|
|
//
|
|
|
|
p_person->Genus.Person->SpecialUse = NULL;
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_GUN_OUT;
|
|
|
|
set_persons_personid(p_person);
|
|
set_person_idle (p_person);
|
|
}
|
|
|
|
|
|
|
|
void set_face_pos(
|
|
Thing *p_person,
|
|
SLONG world_x,
|
|
SLONG world_z)
|
|
{
|
|
SLONG dx = world_x - (p_person->WorldPos.X >> 8);
|
|
SLONG dz = world_z - (p_person->WorldPos.Z >> 8);
|
|
|
|
SLONG angle;
|
|
|
|
angle = calc_angle(dx,dz);
|
|
angle += 1024; // People walk and face backwards!
|
|
angle &= 2047;
|
|
|
|
p_person->Draw.Tweened->Angle = angle;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
SLONG set_face_thing(Thing *p_person,Thing *p_target)
|
|
{
|
|
SLONG dx,dz;
|
|
SLONG angle,pangle;
|
|
SLONG angle_diff;
|
|
SLONG dist;
|
|
|
|
dx=(p_target->WorldPos.X-p_person->WorldPos.X)>>8;
|
|
dz=(p_target->WorldPos.Z-p_person->WorldPos.Z)>>8;
|
|
angle = (Arctan(dx,-dz)+1024+2048)&2047;
|
|
|
|
p_person->Draw.Tweened->Angle=angle;
|
|
|
|
dist=QDIST2(abs(dx),abs(dz));
|
|
|
|
return(dist);
|
|
}
|
|
|
|
void turn_towards_thing(Thing *p_person,Thing *p_target)
|
|
{
|
|
SLONG dx,dz;
|
|
SLONG angle,dangle;
|
|
SLONG angle_diff;
|
|
SLONG dist;
|
|
|
|
dx=(p_target->WorldPos.X-p_person->WorldPos.X)>>8;
|
|
dz=(p_target->WorldPos.Z-p_person->WorldPos.Z)>>8;
|
|
angle = (Arctan(dx,-dz)+1024+2048)&2047;
|
|
|
|
dangle=p_person->Draw.Tweened->Angle-angle;
|
|
|
|
if(dangle<-1024)
|
|
dangle+=2048;
|
|
if(dangle>1024)
|
|
dangle-=2048;
|
|
if(dangle<-32)
|
|
p_person->Draw.Tweened->Angle=(p_person->Draw.Tweened->Angle+32)&2047;
|
|
else
|
|
if(dangle>32)
|
|
p_person->Draw.Tweened->Angle=(p_person->Draw.Tweened->Angle-32)&2047;
|
|
}
|
|
|
|
void fn_person_stand_up(Thing *p_person)
|
|
{
|
|
/*
|
|
|
|
SLONG end;
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
struct Command *com;
|
|
com=TO_COMMAND(p_person->Genus.Person->Command);
|
|
|
|
set_person_walking(p_person);
|
|
set_generic_person_state_function(p_person,STATE_NAVIGATING);
|
|
p_person->Genus.Person->NavIndex=com->Data1;
|
|
|
|
}
|
|
*/
|
|
|
|
}
|
|
void fn_person_fight(Thing *p_person)
|
|
{
|
|
Thing *p_target;
|
|
SLONG dist;
|
|
SLONG end;
|
|
|
|
p_target=TO_THING(p_person->Genus.Person->Target);
|
|
ASSERT(0);
|
|
|
|
/*
|
|
|
|
if(p_target->State==STATE_DEAD||p_target->State==STATE_DYING)
|
|
{
|
|
advance_person_command(p_person);
|
|
return;
|
|
}
|
|
*/
|
|
SlideSoundCheck(p_person);
|
|
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_PUNCH1:
|
|
case ANIM_PUNCH2:
|
|
case ANIM_KICK_ROUND1:
|
|
case ANIM_KICK2:
|
|
dist=turn_to_face_thing(p_person,p_target,0);
|
|
if(dist>170)
|
|
{
|
|
set_anim(p_person,ANIM_WALK);
|
|
}
|
|
else
|
|
{
|
|
end=person_normal_animate(p_person);
|
|
if(end==1)
|
|
{
|
|
queue_anim(p_person,ANIM_WALK);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
|
|
/*
|
|
dist=turn_to_face_thing(p_person,p_target);
|
|
|
|
|
|
|
|
|
|
if(dist>256*12)
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim!=ANIM_WALK)
|
|
queue_anim(p_person,ANIM_WALK);
|
|
p_person->Genus.Person->Target=0;
|
|
}
|
|
else if(dist>256*2)
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim!=ANIM_WALK)
|
|
queue_anim(p_person,ANIM_WALK);
|
|
change_velocity_to(p_person,32);
|
|
person_normal_move(p_person);
|
|
}
|
|
else if(dist>160)
|
|
{
|
|
if(p_person->Draw.Tweened->CurrentAnim!=ANIM_WALK)
|
|
queue_anim(p_person,ANIM_WALK);
|
|
change_velocity_to(p_person,16);
|
|
person_normal_move(p_person);
|
|
}
|
|
else
|
|
{
|
|
if(dist>100)
|
|
{
|
|
if(dist&1)
|
|
queue_anim(p_person,ANIM_PUNCH1);
|
|
else
|
|
queue_anim(p_person,ANIM_KICK_ROUND1);
|
|
}
|
|
else
|
|
queue_anim(p_person,ANIM_STAND_HIP);
|
|
}
|
|
|
|
person_normal_animate(p_person);
|
|
*/
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void set_person_goto_xz(Thing *p_person, SLONG x, SLONG z, SLONG speed)
|
|
{
|
|
SLONG velocity;
|
|
|
|
if (p_person->SubState == SUB_STATE_SLIPPING)
|
|
{
|
|
//
|
|
// Wait till you've reached the bottom of the slope...
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
if (PersonIsMIB(p_person))
|
|
{
|
|
//
|
|
// MIB are too cool to run anywhere.
|
|
//
|
|
|
|
speed = PERSON_SPEED_WALK;
|
|
}
|
|
|
|
//
|
|
// Remember where we are going.
|
|
//
|
|
|
|
p_person->Genus.Person->GotoSpeed = speed;
|
|
p_person->Genus.Person->GotoX = x;
|
|
p_person->Genus.Person->GotoZ = z;
|
|
|
|
SLONG dx = abs(x - (p_person->WorldPos.X >> 8));
|
|
SLONG dz = abs(z - (p_person->WorldPos.Z >> 8));
|
|
|
|
if (QDIST2(dx,dz) < 0x40)
|
|
{
|
|
//
|
|
// Barely worth moving!
|
|
//
|
|
|
|
if (p_person->State != STATE_IDLE &&
|
|
p_person->State != STATE_GUN)
|
|
{
|
|
set_person_idle(p_person);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Correct speed
|
|
//
|
|
|
|
switch(speed)
|
|
{
|
|
case PERSON_SPEED_WALK:
|
|
|
|
if (p_person->SubState != SUB_STATE_WALKING)
|
|
{
|
|
set_anim_walking(p_person);
|
|
// set_anim(p_person,ANIM_WALK);
|
|
|
|
p_person->SubState = SUB_STATE_WALKING;
|
|
p_person->Genus.Person->Action = ACTION_WALK;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Sometimes speed is not set properly...
|
|
//
|
|
|
|
speed = PERSON_SPEED_RUN;
|
|
|
|
p_person->Genus.Person->GotoSpeed = speed;
|
|
|
|
// FALLTHROUGH!
|
|
|
|
case PERSON_SPEED_SPRINT:
|
|
case PERSON_SPEED_RUN:
|
|
|
|
if (p_person->SubState != SUB_STATE_RUNNING)
|
|
{
|
|
set_anim_running(p_person);
|
|
//set_anim(p_person,ANIM_RUN);
|
|
|
|
p_person->SubState = SUB_STATE_RUNNING;
|
|
p_person->Genus.Person->Action = ACTION_RUN;
|
|
}
|
|
|
|
break;
|
|
|
|
case PERSON_SPEED_SNEAK:
|
|
|
|
if (p_person->SubState != SUB_STATE_SNEAKING)
|
|
{
|
|
set_anim(p_person,ANIM_SNEAK);
|
|
|
|
p_person->SubState = SUB_STATE_SNEAKING;
|
|
p_person->Genus.Person->Action = ACTION_WALK;
|
|
}
|
|
|
|
break;
|
|
|
|
case PERSON_SPEED_YOMP:
|
|
|
|
if (p_person->SubState != SUB_STATE_RUNNING)
|
|
{
|
|
if(person_has_special(p_person, SPECIAL_BASEBALLBAT))
|
|
{
|
|
set_anim(p_person,ANIM_YOMP_START_BAT);
|
|
|
|
}
|
|
else
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
set_anim(p_person,ANIM_YOMP_START_AK);
|
|
|
|
}
|
|
else
|
|
{
|
|
if(p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
set_anim(p_person,ANIM_YOMP_START_PISTOL);
|
|
|
|
}
|
|
else
|
|
set_anim(p_person,ANIM_YOMP_START);
|
|
}
|
|
|
|
|
|
p_person->SubState = SUB_STATE_RUNNING;
|
|
p_person->Genus.Person->Action = ACTION_RUN;
|
|
}
|
|
|
|
break;
|
|
|
|
case PERSON_SPEED_CRAWL:
|
|
|
|
if (p_person->SubState != SUB_STATE_CRAWLING)
|
|
{
|
|
locked_anim_change(
|
|
p_person,
|
|
SUB_OBJECT_LEFT_FOOT,
|
|
ANIM_CRAWL);
|
|
|
|
p_person->SubState = SUB_STATE_CRAWLING;
|
|
p_person->Genus.Person->Action = ACTION_CRAWLING;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
p_person->Genus.Person->Flags &= ~(FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C);
|
|
|
|
//
|
|
// How fast?
|
|
//
|
|
|
|
velocity = 50;
|
|
|
|
switch(speed)
|
|
{
|
|
case PERSON_SPEED_WALK:
|
|
if(p_person->Genus.Person->PersonType==PERSON_CIV)
|
|
{
|
|
if(!(p_person->Draw.Tweened->MeshID&1))
|
|
velocity=14;
|
|
else
|
|
velocity=10;
|
|
}
|
|
else
|
|
velocity=16;
|
|
break;
|
|
|
|
case PERSON_SPEED_SNEAK:
|
|
case PERSON_SPEED_CRAWL:
|
|
velocity = 13;
|
|
|
|
break;
|
|
|
|
case PERSON_SPEED_YOMP:
|
|
if(p_person->Genus.Person->PersonType==PERSON_THUG_RASTA)
|
|
{
|
|
//
|
|
// can't out yomp a rasta, can out sprint though
|
|
//
|
|
// velocity +=10;
|
|
}
|
|
else
|
|
velocity -= velocity >> 2;
|
|
break;
|
|
|
|
case PERSON_SPEED_RUN:
|
|
case PERSON_SPEED_SPRINT:
|
|
|
|
if (p_person->Genus.Person->pcom_ai == PCOM_AI_CIV ||
|
|
p_person->Genus.Person->pcom_ai_state != PCOM_AI_STATE_FOLLOWING)
|
|
{
|
|
//
|
|
// Make civs run slower.
|
|
//
|
|
|
|
velocity = 30;
|
|
}
|
|
else
|
|
if(p_person->Genus.Person->PersonType==PERSON_THUG_RASTA)
|
|
{
|
|
//
|
|
// can't out yomp a rasta, can out sprint though
|
|
//
|
|
velocity +=10;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
set_thing_velocity(p_person, velocity);
|
|
|
|
//
|
|
// Change state.
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_GOTOING);
|
|
}
|
|
|
|
|
|
void fn_person_goto(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG dist;
|
|
|
|
SLONG cangle;
|
|
SLONG wangle;
|
|
SLONG dangle;
|
|
|
|
if (p_person->SubState == SUB_STATE_RUNNING_VAULT)
|
|
{
|
|
process_a_vaulting_person(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Animate the person.
|
|
//
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end == 1)
|
|
{
|
|
switch(p_person->Draw.Tweened->CurrentAnim)
|
|
{
|
|
case ANIM_HIT_WALL:
|
|
case ANIM_YOMP_START:
|
|
case ANIM_YOMP_START_PISTOL:
|
|
case ANIM_YOMP_START_AK:
|
|
case ANIM_YOMP_START_BAT:
|
|
|
|
{
|
|
UWORD anim;
|
|
|
|
anim=get_yomp_anim(p_person);
|
|
if(anim==COP_ROPER_ANIM_RUN)
|
|
{
|
|
set_anim_of_type(p_person,anim,ANIM_TYPE_ROPER);
|
|
}
|
|
else
|
|
set_anim(p_person,anim);
|
|
}
|
|
|
|
break;
|
|
}
|
|
/*
|
|
if (p_person->Draw.Tweened->CurrentAnim == ANIM_YOMP_START)
|
|
{
|
|
set_anim(p_person,ANIM_YOMP);
|
|
}
|
|
if (p_person->Draw.Tweened->CurrentAnim == ANIM_YOMP_START_AK)
|
|
{
|
|
set_anim(p_person,ANIM_AK_JOG);
|
|
}
|
|
*/
|
|
}
|
|
|
|
//
|
|
// Point the person towards where he wants to go.
|
|
//
|
|
|
|
dx = p_person->Genus.Person->GotoX - (p_person->WorldPos.X >> 8);
|
|
dz = p_person->Genus.Person->GotoZ - (p_person->WorldPos.Z >> 8);
|
|
|
|
cangle = p_person->Draw.Tweened->Angle;
|
|
wangle = Arctan(dx,-dz) - 1024;
|
|
wangle &= 2047;
|
|
dangle = wangle - cangle;
|
|
dist = abs(dx) + abs(dz);
|
|
|
|
if (dist < 0x100)
|
|
{
|
|
p_person->Draw.Tweened->Angle = wangle;
|
|
}
|
|
else
|
|
{
|
|
if (dangle > 1024) {dangle -= 2048;}
|
|
if (dangle < -1024) {dangle += 2048;}
|
|
|
|
if (dangle > 500) {dangle = 500;}
|
|
if (dangle < -500) {dangle = -500;}
|
|
|
|
p_person->Draw.Tweened->AngleTo = wangle;
|
|
p_person->Draw.Tweened->Angle = cangle + (dangle >> 1);
|
|
p_person->Draw.Tweened->Angle &= 2047;
|
|
}
|
|
|
|
//
|
|
// Move the person.
|
|
//
|
|
|
|
person_normal_move_check(p_person);
|
|
|
|
if (p_person->SubState == SUB_STATE_SLIPPING)
|
|
{
|
|
set_generic_person_state_function(p_person, STATE_MOVEING);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Make navigating people able to vault fences because the navigation
|
|
// system ignores these little vaultable fences.
|
|
//
|
|
|
|
if (last_slide_colvect && is_facet_vaultable(last_slide_colvect))
|
|
{
|
|
set_person_vault(
|
|
p_person,
|
|
last_slide_colvect);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If this person wants to do a running jump...
|
|
//
|
|
|
|
if (p_person->SubState == SUB_STATE_RUNNING_THEN_JUMP)
|
|
{
|
|
switch(p_person->Draw.Tweened->FrameIndex)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
set_person_running_jump_lr(p_person, 1);
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
set_person_running_jump_lr(p_person, 0);
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
AENG_world_line(
|
|
(p_person->WorldPos.X >> 8),
|
|
(p_person->WorldPos.Y >> 8),
|
|
(p_person->WorldPos.Z >> 8),
|
|
0x10,
|
|
0x00ffffff,
|
|
p_person->Genus.Person->GotoX,
|
|
PAP_calc_map_height_at(p_person->Genus.Person->GotoX, p_person->Genus.Person->GotoZ),
|
|
p_person->Genus.Person->GotoZ,
|
|
0x0,
|
|
0x00ff0000,
|
|
TRUE);
|
|
*/
|
|
}
|
|
|
|
#ifdef UNUSED
|
|
SLONG hit_enemy(Thing *p_person,SLONG dx,SLONG dz)
|
|
{
|
|
|
|
SLONG strike;
|
|
// return(0);
|
|
// if(GAME_TURN&1)
|
|
strike=set_person_punch_if_can(p_person);
|
|
if(strike)
|
|
{
|
|
MSG_add(" apply hit \n");
|
|
}
|
|
p_person->StateFn = fn_person_mavigate;
|
|
// set_generic_person_just_function(p_person,STATE_MAVIGATING);
|
|
return(strike);
|
|
}
|
|
#endif
|
|
//
|
|
// Returns TRUE if you've reached your destination.
|
|
//
|
|
|
|
SLONG process_person_goto_xz(Thing *p_person,SLONG x,SLONG z,SLONG dist)
|
|
{
|
|
ASSERT(0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void fn_person_navigate(Thing *p_person)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
void init_person_command(Thing *p_person)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
SLONG mav_arrived(Thing *p_person)
|
|
{
|
|
ASSERT(0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
SLONG person_mav_again(Thing *p_person)
|
|
{
|
|
ASSERT(0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
UWORD dir_to_angle[]=
|
|
{
|
|
512,
|
|
512+1024,
|
|
0,
|
|
1024
|
|
};
|
|
|
|
void get_dx_dz_for_dir(SLONG dir,SLONG *dx,SLONG *dz)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
void init_new_mav(Thing *p_person)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
void fn_person_mavigate_action(Thing *p_person)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
void fn_person_mavigate(Thing *p_person)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
void set_person_grappling_hook_pickup(Thing *p_person)
|
|
{
|
|
//
|
|
// Do the pickup hook animation.
|
|
//
|
|
|
|
set_anim(p_person, ANIM_GRAPPLING_HOOK_PICKUP);
|
|
|
|
//
|
|
// Enter the pickup state.
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_GRAPPLING);
|
|
|
|
p_person->SubState = SUB_STATE_GRAPPLING_PICKUP;
|
|
}
|
|
|
|
|
|
|
|
void fn_person_grapple(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
#ifndef PSX
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_GRAPPLING_PICKUP:
|
|
|
|
if (p_person->Draw.Tweened->FrameIndex == 2) // i.e. if you have reached the bottom of the pickup animation
|
|
{
|
|
SLONG px;
|
|
SLONG py;
|
|
SLONG pz;
|
|
|
|
//
|
|
// Pickup the grappling hook.
|
|
//
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_RIGHT_HAND,
|
|
&px,
|
|
&py,
|
|
&pz);
|
|
|
|
px += p_person->WorldPos.X >> 8;
|
|
py += p_person->WorldPos.Y >> 8;
|
|
pz += p_person->WorldPos.Z >> 8;
|
|
|
|
HOOK_spin(
|
|
px,
|
|
py,
|
|
pz,
|
|
p_person->Draw.Tweened->Angle,
|
|
50);
|
|
|
|
//
|
|
// Mark the person as having the grappling hook.
|
|
//
|
|
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_GRAPPLING;
|
|
}
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end)
|
|
{
|
|
//
|
|
// Start spinning it.
|
|
//
|
|
|
|
set_person_grapple_windup(p_person);
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_GRAPPLING_WINDUP:
|
|
|
|
person_normal_animate_speed(p_person, 256);
|
|
|
|
break;
|
|
|
|
case SUB_STATE_GRAPPLING_RELEASE:
|
|
|
|
//
|
|
// If you have reached the bottom of the pickup animation for
|
|
// the first time.
|
|
//
|
|
|
|
if (/*p_person->Draw.Tweened->FrameIndex == 2 &&*/ HOOK_get_state() == HOOK_STATE_SPINNING)
|
|
{
|
|
//
|
|
// Release the grappling hook.
|
|
//
|
|
|
|
HOOK_release();
|
|
|
|
//
|
|
// We don't have it anymore.
|
|
//
|
|
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_GRAPPLING;
|
|
}
|
|
|
|
end = person_normal_animate_speed(p_person, 512);
|
|
|
|
if (end)
|
|
{
|
|
//
|
|
// Nothing more to do now.
|
|
//
|
|
|
|
set_person_idle(p_person);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
void set_person_mav_to_xz(Thing *p_person,SLONG x,SLONG z)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
void set_person_mav_to_thing(Thing *p_person,Thing *p_target)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
#if !defined(TARGET_DC) && !defined(PSX)
|
|
SLONG person_is_on_sewer(Thing *p_person) {
|
|
NS_Hi *ns;
|
|
ns=&NS_hi[p_person->WorldPos.X>>(8+PAP_SHIFT_HI)][p_person->WorldPos.Z>>(8+PAP_SHIFT_HI)];
|
|
if (ns->packed&NS_HI_FLAG_GRATE) return PERSON_ON_METAL;
|
|
if (ns->water) return PERSON_ON_SEWATER;
|
|
return PERSON_ON_WATER;
|
|
}
|
|
#endif
|
|
|
|
SLONG person_is_on(Thing *p_person)
|
|
{
|
|
#if !defined(PSX) && !defined(TARGET_DC)
|
|
if (GAME_FLAGS & GF_SEWERS)
|
|
{
|
|
if (p_person->Flags & FLAGS_IN_SEWERS) {
|
|
return person_is_on_sewer(p_person);
|
|
}
|
|
}
|
|
#endif
|
|
if (p_person->OnFace)
|
|
{
|
|
//
|
|
// Does this face belong to a prim?
|
|
//
|
|
|
|
if (p_person->OnFace > 0)
|
|
{
|
|
if(prim_faces4[p_person->OnFace].FaceFlags&FACE_FLAG_METAL)
|
|
{
|
|
return PERSON_ON_METAL;
|
|
}
|
|
// if (prim_faces4[p_person->OnFace].ThingIndex > 0)
|
|
{
|
|
return PERSON_ON_PRIM;
|
|
}
|
|
}
|
|
}
|
|
// else
|
|
{
|
|
//
|
|
// Standing in a puddle?
|
|
//
|
|
#ifndef PSX
|
|
#ifndef TARGET_DC
|
|
if (PUDDLE_in(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Z >> 8))
|
|
{
|
|
return PERSON_ON_WATER;
|
|
}
|
|
#endif
|
|
#endif
|
|
//
|
|
// Check for special floor textures...
|
|
//
|
|
|
|
SLONG mx = p_person->WorldPos.X >> 16;
|
|
SLONG mz = p_person->WorldPos.Z >> 16;
|
|
|
|
if (WITHIN(mx, 0, MAP_WIDTH - 1) &&
|
|
WITHIN(mz, 0, MAP_HEIGHT - 1))
|
|
{
|
|
#ifdef PSX
|
|
// page=255;
|
|
return(-255);
|
|
#else
|
|
|
|
SLONG page = PAP_2HI(mx,mz).Texture & 0x3ff;
|
|
|
|
page=SOUND_FXMapping[page];
|
|
|
|
if (page==255) page=5;
|
|
|
|
if (page==0) return 255; // god this SUCKS SO HARD! sorry
|
|
|
|
return -page;
|
|
#endif
|
|
|
|
//return -SOUND_FXMapping[page];
|
|
|
|
/* if (page == 65 ||
|
|
page == 66 ||
|
|
page == 143)
|
|
{
|
|
return PERSON_ON_WOOD;
|
|
}
|
|
|
|
if (page >= 69 && page <= 74)
|
|
{
|
|
return PERSON_ON_GRASS;
|
|
}
|
|
|
|
if (page == 68 || (page >= 106 && page <= 111))
|
|
{
|
|
return PERSON_ON_GRAVEL;
|
|
}*/
|
|
}
|
|
}
|
|
|
|
return PERSON_ON_DUNNO;
|
|
}
|
|
|
|
|
|
void set_person_can_pickup(Thing *p_person)
|
|
{
|
|
//
|
|
// Do the pickup can animation.
|
|
//
|
|
|
|
set_anim(p_person, ANIM_CAN_PICKUP);
|
|
|
|
//
|
|
// Enter the pickup state.
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_CANNING);
|
|
|
|
p_person->SubState = SUB_STATE_CANNING_PICKUP;
|
|
}
|
|
|
|
void set_person_can_release(Thing *p_person, SLONG power)
|
|
{
|
|
Thing *p_special;
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_CANNING)
|
|
{
|
|
goto something_to_throw;
|
|
}
|
|
|
|
if (p_person->Genus.Person->SpecialUse)
|
|
{
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
if (p_special->Genus.Special->SpecialType == SPECIAL_GRENADE)
|
|
{
|
|
//
|
|
// We have a grenade to throw
|
|
//
|
|
|
|
goto something_to_throw;
|
|
}
|
|
}
|
|
|
|
p_special = person_has_special(p_person, SPECIAL_MINE);
|
|
|
|
if (p_special->SubState == SPECIAL_SUBSTATE_ACTIVATED)
|
|
{
|
|
//
|
|
// We have an activated mine to throw.
|
|
//
|
|
|
|
goto something_to_throw;
|
|
}
|
|
|
|
return;
|
|
|
|
something_to_throw:;
|
|
|
|
//
|
|
// Do the throw can animation.
|
|
//
|
|
|
|
set_anim(p_person, ANIM_CAN_RELEASE);
|
|
|
|
//
|
|
// Enter the throw a can state.
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_CANNING);
|
|
|
|
p_person->SubState = SUB_STATE_CANNING_RELEASE;
|
|
}
|
|
|
|
/*
|
|
void set_person_barrel_pickup(Thing *p_person)
|
|
{
|
|
//
|
|
// Do the pickup barrel animation.
|
|
//
|
|
|
|
set_anim(p_person, ANIM_LOB2);
|
|
|
|
//
|
|
// Enter the throw a can state.
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_CANNING);
|
|
|
|
p_person->SubState = SUB_STATE_CANNING_GET_BARREL;
|
|
}
|
|
*/
|
|
|
|
void set_person_special_pickup(Thing *p_person)
|
|
{
|
|
//
|
|
// Do the pickup can animation.
|
|
//
|
|
|
|
set_anim(p_person, ANIM_CAN_PICKUP);
|
|
|
|
//
|
|
// Enter the pickup special state.
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_CANNING);
|
|
|
|
p_person->SubState = SUB_STATE_CANNING_GET_SPECIAL;
|
|
}
|
|
|
|
void fn_person_can(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_CANNING_PICKUP:
|
|
|
|
// if (p_person->Draw.Tweened->FrameIndex == 4) // i.e. if you have reached the bottom of the pickup animation
|
|
|
|
// cunnnnning
|
|
if (p_person->Draw.Tweened->FrameIndex == (3+p_person->Genus.Person->AnimType))
|
|
{
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_CANNING)
|
|
{
|
|
//
|
|
// Already got a can.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Find the position of your right hand.
|
|
//
|
|
|
|
MFX_play_thing(THING_NUMBER(p_person),S_PICKUP_SWISH,0,p_person);
|
|
|
|
SLONG px;
|
|
SLONG py;
|
|
SLONG pz;
|
|
|
|
calc_sub_objects_position(
|
|
p_person,
|
|
p_person->Draw.Tweened->AnimTween,
|
|
SUB_OBJECT_PREFERRED_HAND,
|
|
&px,
|
|
&py,
|
|
&pz);
|
|
|
|
px += p_person->WorldPos.X >> 8;
|
|
py += p_person->WorldPos.Y >> 8;
|
|
pz += p_person->WorldPos.Z >> 8;
|
|
|
|
//
|
|
// Pickup the nearest coke can or head
|
|
//
|
|
|
|
DIRT_pick_up_can_or_head(p_person);
|
|
}
|
|
}
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end)
|
|
{
|
|
//
|
|
// Finished picking-up the coke can or head
|
|
//
|
|
|
|
set_person_idle(p_person);
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_CANNING_RELEASE:
|
|
|
|
{
|
|
// SLONG when = (p_person->Genus.Person->AnimType==ANIM_TYPE_ROPER) ? 7 : 3;
|
|
|
|
if (p_person->Draw.Tweened->FrameIndex == 3) // i.e. reached the release part of the anim.
|
|
{
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_CANNING)
|
|
{
|
|
//
|
|
// Throwing a coke can or a head.
|
|
//
|
|
|
|
DIRT_release_can_or_head(p_person, 128);
|
|
}
|
|
else
|
|
{
|
|
Thing *p_special;
|
|
|
|
//
|
|
// Throwing a grenade or a mine.
|
|
//
|
|
|
|
if (p_person->Genus.Person->SpecialUse &&
|
|
TO_THING(p_person->Genus.Person->SpecialUse)->Genus.Special->SpecialType == SPECIAL_GRENADE)
|
|
{
|
|
p_special = TO_THING(p_person->Genus.Person->SpecialUse);
|
|
|
|
if (p_special->SubState == SPECIAL_SUBSTATE_ACTIVATED)
|
|
{
|
|
SPECIAL_throw_grenade(TO_THING(p_person->Genus.Person->SpecialUse));
|
|
}
|
|
}
|
|
/*
|
|
|
|
//
|
|
// You can't throw mines any more.
|
|
//
|
|
|
|
else
|
|
{
|
|
p_special = person_has_special(p_person, SPECIAL_MINE);
|
|
|
|
if (p_special)
|
|
{
|
|
if (p_special->SubState == SPECIAL_SUBSTATE_ACTIVATED)
|
|
{
|
|
SPECIAL_throw_mine(p_special);
|
|
}
|
|
}
|
|
}
|
|
|
|
*/
|
|
}
|
|
}
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end)
|
|
{
|
|
//
|
|
// Finished throwing the can or head.
|
|
//
|
|
|
|
set_person_idle(p_person);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_CANNING_GET_BARREL:
|
|
|
|
ASSERT(0);
|
|
|
|
/*
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end)
|
|
{
|
|
//
|
|
// Finished throwing the barrel.
|
|
//
|
|
|
|
set_person_idle(p_person);
|
|
|
|
return;
|
|
}
|
|
|
|
if (p_person->Draw.Tweened->FrameIndex == 2)
|
|
{
|
|
if (!(p_person->Genus.Person->Flags & FLAG_PERSON_BARRELING))
|
|
{
|
|
//
|
|
// Find a barrel to pickup.
|
|
//
|
|
|
|
p_person->Genus.Person->Hold = THING_find_nearest(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
0x80,
|
|
(1 << CLASS_BARREL));
|
|
|
|
if (p_person->Genus.Person->Hold == NULL)
|
|
{
|
|
//
|
|
// No barrel to pickup.
|
|
//
|
|
|
|
set_person_idle(p_person);
|
|
}
|
|
else
|
|
{
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_BARRELING;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_BARRELING)
|
|
|
|
{
|
|
BARREL_position_on_hands(TO_THING(p_person->Genus.Person->Hold), p_person);
|
|
}
|
|
|
|
{
|
|
if (p_person->Draw.Tweened->FrameIndex == 9 || (p_person->Draw.Tweened->FrameIndex == 8 && p_person->Draw.Tweened->AnimTween >= 128))
|
|
{
|
|
|
|
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_BARRELING)
|
|
{
|
|
//
|
|
// Release the barrel.
|
|
//
|
|
|
|
BARREL_throw(TO_THING(p_person->Genus.Person->Hold));
|
|
|
|
p_person->Genus.Person->Flags &= ~FLAG_PERSON_BARRELING;
|
|
}
|
|
}
|
|
}
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
case SUB_STATE_CANNING_GET_SPECIAL:
|
|
|
|
if (p_person->Draw.Tweened->FrameIndex == (3+p_person->Genus.Person->AnimType))
|
|
{
|
|
UWORD s_index;
|
|
Thing *s_thing;
|
|
|
|
MFX_play_thing(THING_NUMBER(p_person),S_PICKUP_SWISH,0,p_person);
|
|
s_index = THING_find_nearest(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Y >> 8,
|
|
p_person->WorldPos.Z >> 8,
|
|
0xa0,
|
|
1 << CLASS_SPECIAL);
|
|
|
|
if (s_index)
|
|
{
|
|
s_thing = TO_THING(s_index);
|
|
|
|
if (should_person_get_item(p_person, s_thing))
|
|
{
|
|
person_get_item(p_person, s_thing);
|
|
|
|
//
|
|
// Don't check for specials anymore.
|
|
//
|
|
|
|
p_person->SubState = SUB_STATE_CANNING_GOT_SPECIAL;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// FALLTHROUGH!
|
|
//
|
|
|
|
case SUB_STATE_CANNING_GOT_SPECIAL:
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end)
|
|
{
|
|
//
|
|
// Finished picking up the special.
|
|
//
|
|
|
|
set_person_idle(p_person);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void set_person_do_a_simple_anim(Thing *p_person, SLONG anim)
|
|
{
|
|
set_anim(p_person, anim);
|
|
set_generic_person_state_function(p_person, STATE_MOVEING);
|
|
p_person->SubState = SUB_STATE_SIMPLE_ANIM;
|
|
p_person->Genus.Person->Flags |= FLAG_PERSON_NON_INT_M|FLAG_PERSON_NON_INT_C;
|
|
}
|
|
|
|
|
|
|
|
void set_person_recircle(Thing *p_person)
|
|
{
|
|
SLONG anim;
|
|
ASSERT(p_person->Genus.Person->PlayerID==0);
|
|
|
|
if (p_person->Genus.Person->Target == NULL)
|
|
{
|
|
//
|
|
// This person has no target... lets find him one!
|
|
//
|
|
|
|
p_person->Genus.Person->Target = PCOM_person_wants_to_kill(p_person);
|
|
}
|
|
|
|
if(p_person->SubState==SUB_STATE_BLOCK)
|
|
return;
|
|
if (p_person->Genus.Person->Flags&FLAG_PERSON_REQUEST_BLOCK)
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_BLOCK;
|
|
|
|
//
|
|
// person has decided to do a block so, do a block
|
|
//
|
|
|
|
set_person_block(p_person);
|
|
return;
|
|
}
|
|
|
|
|
|
anim=find_idle_fight_stance(p_person);
|
|
set_anim(p_person, anim);
|
|
p_person->Genus.Person->Timer1=0;
|
|
set_generic_person_state_function(p_person, STATE_CIRCLING);
|
|
if(p_person->Genus.Person->Agression>-10)
|
|
p_person->SubState = SUB_STATE_CIRCLING_CIRCLE;
|
|
else
|
|
p_person->SubState = SUB_STATE_CIRCLING_BACK_OFF;
|
|
p_person->Genus.Person->Mode=PERSON_MODE_FIGHT;
|
|
}
|
|
|
|
void set_person_circle(Thing *p_person, Thing *p_target)
|
|
{
|
|
SLONG dx,dy,dz;
|
|
SLONG anim;
|
|
//
|
|
// Remember who we are circling.
|
|
//
|
|
ASSERT(p_person->Genus.Person->PlayerID==0);
|
|
|
|
p_person->Genus.Person->Target = THING_NUMBER(p_target);
|
|
ASSERT(p_person->Genus.Person->Target !=THING_NUMBER(p_person));
|
|
ASSERT(TO_THING(p_person->Genus.Person->Target)->Class==CLASS_PERSON);
|
|
p_person->Genus.Person->Timer1=0;
|
|
ASSERT(p_person->Genus.Person->Target != THING_NUMBER(p_person));
|
|
|
|
//
|
|
// Do the fighting animation.
|
|
//
|
|
anim=find_idle_fight_stance(p_person);
|
|
|
|
set_anim(p_person, anim);
|
|
|
|
//
|
|
// Enter the cirling state.
|
|
//
|
|
|
|
set_generic_person_state_function(p_person, STATE_CIRCLING);
|
|
|
|
p_person->SubState = SUB_STATE_CIRCLING_BACK_OFF;
|
|
//
|
|
// STACK collide_against_things/sweep_feet/attack_happened/set_person_ai_kill/pcomset_move_circle
|
|
//
|
|
// calc_sub_objects_position(p_target,p_target->Draw.Tweened->AnimTween,SUB_OBJECT_PELVIS,&dx,&dy,&dz);
|
|
p_person->Genus.Person->TargetX=(p_target->WorldPos.X>>8);//+dx;
|
|
p_person->Genus.Person->TargetZ=(p_target->WorldPos.Z>>8);//+dz;
|
|
p_person->Genus.Person->Agression=-21;
|
|
p_person->Genus.Person->Mode=PERSON_MODE_FIGHT;
|
|
|
|
}
|
|
|
|
void set_person_hug_wall_leap_out(Thing *p_person,SLONG dir)
|
|
{
|
|
SLONG anim;
|
|
p_person->SubState=SUB_STATE_HUG_WALL_LEAP_OUT;
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
anim=ANIM_PRESS_WALL_FREEZE_L_PISTOL;
|
|
}
|
|
else
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
anim=ANIM_PRESS_WALL_FREEZE_L_AK;
|
|
}
|
|
else
|
|
{
|
|
anim=ANIM_PRESS_WALL_FREEZE_L;
|
|
}
|
|
if(dir==1)
|
|
anim++;
|
|
// set_locked_anim(p_person,anim,SUB_OBJECT_LEFT_FOOT);
|
|
set_anim(p_person,anim);
|
|
p_person->Genus.Person->Action=ACTION_NONE;
|
|
|
|
}
|
|
void set_person_hug_wall_stand(Thing *p_person,SLONG dangle=0,SLONG locked=1)
|
|
{
|
|
SLONG anim;
|
|
SLONG dist,dx,dz;
|
|
p_person->SubState=SUB_STATE_HUG_WALL_STAND;
|
|
if (p_person->Genus.Person->Flags & FLAG_PERSON_GUN_OUT)
|
|
{
|
|
anim=ANIM_PRESS_WALL_STAND_PISTOL;
|
|
}
|
|
else
|
|
if(person_holding_2handed(p_person))
|
|
{
|
|
anim=ANIM_PRESS_WALL_STAND_AK;
|
|
}
|
|
else
|
|
{
|
|
anim=ANIM_PRESS_WALL_STAND;
|
|
}
|
|
if(!locked)
|
|
{
|
|
set_anim(p_person,anim);
|
|
}
|
|
else
|
|
{
|
|
set_locked_anim_angle(p_person,anim,SUB_OBJECT_PELVIS,dangle);
|
|
}
|
|
/*
|
|
if((dist=abs(check_near_facet(p_person,64,64,(p_person->WorldPos.X)>>8,(p_person->WorldPos.Z)>>8)))==0)
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
if(abs(32-dist)<32)
|
|
{
|
|
SLONG angle;
|
|
angle=(p_person->Draw.Tweened->Angle)&2047;
|
|
|
|
dx = -(SIN(angle) * (32-dist)) >> 8;
|
|
dz = -(COS(angle) * (32-dist)) >> 8;
|
|
person_normal_move_dxdz(p_person,dx,dz);
|
|
|
|
}
|
|
*/
|
|
|
|
|
|
// set_anim(p_person,anim);
|
|
|
|
}
|
|
|
|
//
|
|
// returns true if person is within max_dist of a facet
|
|
//
|
|
extern SLONG global_on;
|
|
UWORD near_facet=0;
|
|
SLONG check_near_facet(Thing *p_person,SLONG max_dist,SLONG max_end_dist,SLONG px,SLONG pz)
|
|
{
|
|
SLONG loop=4;
|
|
SLONG mx,mz;
|
|
SLONG c0,exit,f_list,i_facet;
|
|
struct DFacet *df;
|
|
SLONG y_top,y_bot,pers_y;
|
|
SLONG best_dist=99999;
|
|
SLONG person_north_south=0;
|
|
|
|
SUPERMAP_counter_increase(0);
|
|
near_facet=0;
|
|
/*
|
|
AENG_world_line(
|
|
(p_person->WorldPos.X >> 8),
|
|
(p_person->WorldPos.Y >> 8),
|
|
(p_person->WorldPos.Z >> 8),
|
|
3,
|
|
0x00ffffff,
|
|
px,
|
|
(p_person->WorldPos.Y)>>8,
|
|
pz,
|
|
0,
|
|
0x00123456,
|
|
TRUE);
|
|
*/
|
|
|
|
{
|
|
SLONG a;
|
|
a=p_person->Draw.Tweened->Angle&2047;
|
|
if(a<200 || a>2048-200 || (a>1024-200 && a<1024+200))
|
|
{
|
|
person_north_south=1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pers_y=(p_person->WorldPos.Y>>8)+128;
|
|
|
|
while(loop>=0)
|
|
{
|
|
mx=px>>10;
|
|
mz=pz>>10;
|
|
|
|
switch(loop)
|
|
{
|
|
case 4:
|
|
break;
|
|
case 3:
|
|
mx++;
|
|
break;
|
|
case 2:
|
|
mx--;
|
|
break;
|
|
case 1:
|
|
mz++;
|
|
break;
|
|
case 0:
|
|
mz--;
|
|
break;
|
|
}
|
|
loop--;
|
|
exit = FALSE;
|
|
if(mx>=0 && mz>=0 && mx<32 && mz<32)
|
|
{
|
|
f_list = PAP_2LO(mx,mz).ColVectHead;
|
|
|
|
if (!f_list)
|
|
{
|
|
//
|
|
// No facets on this square.
|
|
//
|
|
|
|
exit=1;
|
|
}
|
|
|
|
while(!exit)
|
|
{
|
|
|
|
i_facet = facet_links[f_list++];
|
|
ASSERT(i_facet<next_dfacet);
|
|
|
|
if (i_facet < 0)
|
|
{
|
|
i_facet = -i_facet;
|
|
exit = TRUE;
|
|
}
|
|
|
|
df = &dfacets[i_facet];
|
|
|
|
//
|
|
// Done this one already?
|
|
//
|
|
|
|
if (df->Counter[0] == SUPERMAP_counter[0])
|
|
{
|
|
//
|
|
// We've done this facet already.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Mark this facet as already done.
|
|
//
|
|
|
|
df->Counter[0] = SUPERMAP_counter[0];
|
|
|
|
if (df->FacetType == STOREY_TYPE_CABLE)
|
|
{
|
|
//
|
|
// Ignore cables in collision.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
if (df->FacetType == STOREY_TYPE_OUTSIDE_DOOR && (df->FacetFlags & FACET_FLAG_OPEN))
|
|
{
|
|
//
|
|
// Ignore open doors.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
if((person_north_south && (df->x[0]==df->x[1]) ) ||( (!person_north_south) && (df->z[0]==df->z[1]) ) )
|
|
{
|
|
//
|
|
// looking for facets in other plane
|
|
//
|
|
continue;
|
|
|
|
}
|
|
|
|
//
|
|
// Is the 'y' component in range?
|
|
//
|
|
|
|
if (df->FacetType == STOREY_TYPE_FENCE_FLAT ||
|
|
df->FacetType == STOREY_TYPE_FENCE ||
|
|
df->FacetType == STOREY_TYPE_FENCE_BRICK ||
|
|
df->FacetType == STOREY_TYPE_OUTSIDE_DOOR)
|
|
{
|
|
y_top = get_fence_top (px , pz, i_facet);
|
|
y_bot = get_fence_bottom(px, pz, i_facet) - 30;
|
|
|
|
}
|
|
else
|
|
{
|
|
y_bot = df->Y[0] - 64;
|
|
y_top = df->Y[0] + (df->Height * df->BlockHeight << 2);
|
|
|
|
if (df->FHeight)
|
|
{
|
|
//
|
|
// You can never walk under foundations.
|
|
//
|
|
|
|
y_bot = -0x7fff;
|
|
}
|
|
}
|
|
if (WITHIN(pers_y, y_bot, y_top))
|
|
{
|
|
SLONG dist;
|
|
|
|
dist=distance_to_line(df->x[0]<<8,df->z[0]<<8,df->x[1]<<8,df->z[1]<<8,px,pz);
|
|
// df->FacetFlags|=FACET_FLAG_IN_SEWERS;
|
|
if(global_on)
|
|
if(abs(dist)<abs(best_dist))
|
|
{
|
|
best_dist=dist;
|
|
near_facet=i_facet;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
// PANEL_new_text(p_person,100," best_dist %d dist %d",best_dist,max_dist);
|
|
|
|
if(abs(best_dist)<max_dist)
|
|
{
|
|
return(best_dist);
|
|
}
|
|
/*
|
|
{
|
|
SLONG angle;
|
|
SLONG dx,dz,nx,nz;
|
|
angle=(p_person->Draw.Tweened->Angle+1024)&2047;
|
|
dx = -(SIN(angle) * 128) >> 16;
|
|
dz = -(COS(angle) * 128) >> 16;
|
|
|
|
nx=(px+dx)>>10;
|
|
nz=(pz+dz)>>10;
|
|
|
|
if(nx==mx && nz==mz)
|
|
{
|
|
if(abs(best_dist)<max_dist)
|
|
{
|
|
return(best_dist);
|
|
}
|
|
else
|
|
{
|
|
near_facet=0;
|
|
PANEL_new_text(p_person,3000,"NO HUGb");
|
|
return(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mx=nx;
|
|
mz=nz;
|
|
|
|
}
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
if(abs(best_dist)<max_dist)
|
|
{
|
|
return(best_dist);
|
|
}
|
|
else
|
|
{
|
|
near_facet=0;
|
|
// PANEL_new_text(p_person,3000,"NO HUG");
|
|
return(0);
|
|
}
|
|
|
|
}
|
|
// return angle+1
|
|
SLONG can_i_hug_wall(Thing *p_person)
|
|
{
|
|
if (p_person->OnFace>0)
|
|
{
|
|
ASSERT(WITHIN(p_person->OnFace, 1, next_prim_face4 - 1));
|
|
|
|
PrimFace4 *f4 = &prim_faces4[p_person->OnFace];
|
|
|
|
ASSERT(f4->FaceFlags & FACE_FLAG_WALKABLE);
|
|
|
|
if (f4->FaceFlags & FACE_FLAG_WMOVE)
|
|
{
|
|
return(0); // not while stood on a car etc
|
|
}
|
|
}
|
|
if(p_person->Genus.Person->Ware==0)
|
|
if(check_near_facet(p_person,64,64,p_person->WorldPos.X>>8,p_person->WorldPos.Z>>8))
|
|
{
|
|
SLONG wall_angle,ft;
|
|
ft=dfacets[near_facet].FacetType;
|
|
if(ft==STOREY_TYPE_NORMAL)
|
|
if(am_i_facing_wall(p_person,near_facet,&wall_angle,200))
|
|
{
|
|
SLONG wx,wy,wz;
|
|
SLONG mx,my,mz;
|
|
SLONG dx,dz;
|
|
|
|
wx=p_person->WorldPos.X>>8;
|
|
wy=p_person->WorldPos.Y>>8;
|
|
wz=p_person->WorldPos.Z>>8;
|
|
|
|
dx = -(SIN(wall_angle)) >> 9;
|
|
dz = -(COS(wall_angle)) >> 9;
|
|
|
|
mx=(wx+dx)>>8;
|
|
mz=(wz+dz)>>8;
|
|
|
|
my=MAVHEIGHT(mx,mz)<<6;
|
|
|
|
// if(wy<my-196 || wy>my-64)
|
|
if(wy>my-196)
|
|
return(0);
|
|
|
|
return((wall_angle&2047)+1);
|
|
}
|
|
|
|
|
|
}
|
|
return(0);
|
|
|
|
}
|
|
|
|
SLONG move_ok(Thing *p_person,SLONG dx,SLONG dz)
|
|
{
|
|
SLONG y,dy;
|
|
SLONG nx,nz;
|
|
|
|
nx=p_person->WorldPos.X;
|
|
nz=p_person->WorldPos.Z;
|
|
|
|
nx+=dx;
|
|
nz+=dz;
|
|
|
|
nx>>=8;
|
|
nz>>=8;
|
|
|
|
|
|
y=MAVHEIGHT(nx>>8,nz>>8)<<6;
|
|
|
|
dy=y-(p_person->WorldPos.Y>>8);
|
|
if(abs(dy)>60)
|
|
return(0);
|
|
|
|
if(PAP_2HI(nx >> 8, nz >> 8).Flags & PAP_FLAG_NOGO)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
void fn_person_hug_wall(Thing *p_person)
|
|
{
|
|
SLONG end;
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG angle;
|
|
SLONG dist;
|
|
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_HUG_WALL_TURN:
|
|
end = person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
set_person_hug_wall_stand(p_person,1024);
|
|
// p_person->Draw.Tweened->Angle+=1024;
|
|
// p_person->Draw.Tweened->Angle&=2047;
|
|
}
|
|
break;
|
|
case SUB_STATE_HUG_WALL_STAND:
|
|
|
|
break;
|
|
case SUB_STATE_HUG_WALL_STEP_LEFT:
|
|
if(!continue_dir(p_person,1))
|
|
{
|
|
set_person_hug_wall_stand(p_person);
|
|
return;
|
|
}
|
|
|
|
angle=(p_person->Draw.Tweened->Angle+512)&2047;
|
|
|
|
dx = -(SIN(angle) * 5) >> 8;
|
|
dz = -(COS(angle) * 5) >> 8;
|
|
|
|
if(!move_ok(p_person,dx<<4,dz<<4))
|
|
{
|
|
|
|
set_person_hug_wall_stand(p_person,0,0);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
if((dist=abs(check_near_facet(p_person,64,64,(p_person->WorldPos.X+dx*8)>>8,(p_person->WorldPos.Z+dz*8)>>8)))==0)
|
|
{
|
|
set_person_hug_wall_look(p_person,0);
|
|
// set_person_hug_wall_stand(p_person);
|
|
return;
|
|
}
|
|
|
|
if(abs(32-dist)<32)
|
|
{
|
|
angle=(p_person->Draw.Tweened->Angle)&2047;
|
|
|
|
dx += -(SIN(angle) * (32-dist)) >> 8;
|
|
dz += -(COS(angle) * (32-dist)) >> 8;
|
|
|
|
}
|
|
|
|
person_normal_move_dxdz(p_person,dx,dz);
|
|
end = person_normal_animate(p_person);
|
|
/*
|
|
if(end)
|
|
{
|
|
set_person_hug_wall_stand(p_person);
|
|
}
|
|
*/
|
|
|
|
break;
|
|
case SUB_STATE_HUG_WALL_LEAP_OUT:
|
|
end = person_normal_animate(p_person);
|
|
if(end)
|
|
{
|
|
if(person_has_gun_out(p_person))
|
|
{
|
|
set_person_aim(p_person,SUB_OBJECT_PELVIS+1);
|
|
}
|
|
else
|
|
{
|
|
set_person_locked_idle_ready(p_person);
|
|
}
|
|
p_person->Draw.Tweened->Angle+=1024;
|
|
p_person->Draw.Tweened->Angle&=2047;
|
|
|
|
plant_feet(p_person);
|
|
|
|
// set_person_idle(p_person);
|
|
|
|
}
|
|
|
|
break;
|
|
case SUB_STATE_HUG_WALL_LOOK_L:
|
|
//if(continue_dir(p_person,0))
|
|
if(++p_person->Genus.Person->InsideRoom>16)
|
|
p_person->Genus.Person->InsideRoom=16;
|
|
|
|
end = person_normal_animate(p_person);
|
|
/* else
|
|
{
|
|
set_person_hug_wall_stand(p_person);
|
|
}
|
|
*/
|
|
break;
|
|
case SUB_STATE_HUG_WALL_LOOK_R:
|
|
// if(continue_dir(p_person,1))
|
|
if(++p_person->Genus.Person->InsideRoom>16)
|
|
p_person->Genus.Person->InsideRoom=16;
|
|
end = person_normal_animate(p_person);
|
|
/*
|
|
else
|
|
{
|
|
set_person_hug_wall_stand(p_person);
|
|
}
|
|
*/
|
|
|
|
|
|
break;
|
|
case SUB_STATE_HUG_WALL_STEP_RIGHT:
|
|
if(!continue_dir(p_person,0))
|
|
{
|
|
set_person_hug_wall_stand(p_person);
|
|
return;
|
|
}
|
|
angle=(p_person->Draw.Tweened->Angle-512)&2047;
|
|
|
|
dx = -(SIN(angle) * 5) >> 8;
|
|
dz = -(COS(angle) * 5) >> 8;
|
|
|
|
if(!move_ok(p_person,dx<<4,dz<<4))
|
|
{
|
|
|
|
set_person_hug_wall_stand(p_person,0,0);
|
|
return;
|
|
}
|
|
|
|
if((dist=abs(check_near_facet(p_person,64,64,(p_person->WorldPos.X+dx*8)>>8,(p_person->WorldPos.Z+dz*8)>>8)))==0)
|
|
{
|
|
set_person_hug_wall_look(p_person,1);
|
|
// set_person_hug_wall_stand(p_person);
|
|
return;
|
|
}
|
|
if(abs(32-dist)<32)
|
|
{
|
|
angle=(p_person->Draw.Tweened->Angle)&2047;
|
|
|
|
dx += -(SIN(angle) * (32-dist)) >> 8;
|
|
dz += -(COS(angle) * (32-dist)) >> 8;
|
|
|
|
}
|
|
|
|
person_normal_move_dxdz(p_person,dx,dz);
|
|
end = person_normal_animate(p_person);
|
|
/*
|
|
if(end)
|
|
{
|
|
set_person_hug_wall_stand(p_person);
|
|
}
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
SLONG kick_or_punch = 0;
|
|
|
|
void fn_person_circle(Thing *p_person)
|
|
{
|
|
//
|
|
// start simple orbit the enemy
|
|
//
|
|
|
|
SLONG dx=0;
|
|
SLONG dy;
|
|
SLONG dz=0;
|
|
SLONG end;
|
|
SLONG dist;
|
|
SLONG angle;
|
|
SLONG shove;
|
|
SLONG dangle;
|
|
SLONG random;
|
|
SLONG ddist;
|
|
|
|
SLONG vx = 0;
|
|
SLONG vz = 0;
|
|
UBYTE renav=0;
|
|
UWORD reqd_anim=0;
|
|
|
|
BOOL poo;
|
|
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
SLONG hit_distance=140;
|
|
SLONG bat=0;
|
|
SLONG stamp=0;
|
|
if(person_holding_bat(p_person))
|
|
bat=1;
|
|
|
|
if(p_person->Genus.Person->Target==0)
|
|
{
|
|
set_person_idle(p_person);
|
|
return;
|
|
}
|
|
|
|
if (p_person->Genus.Person->Flags&FLAG_PERSON_REQUEST_BLOCK)
|
|
{
|
|
p_person->Genus.Person->Flags&=~FLAG_PERSON_REQUEST_BLOCK;
|
|
|
|
//
|
|
// person has decided to do a block so, do a block
|
|
//
|
|
|
|
set_person_block(p_person);
|
|
return;
|
|
}
|
|
if((p_target->Genus.Person->PlayerID==0) ||p_person->Genus.Person->PersonType==PERSON_COP)
|
|
p_person->Genus.Person->Agression=100;
|
|
|
|
ASSERT(p_target!=p_person);
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (is_person_ko_and_lay_down(p_target))
|
|
{
|
|
//
|
|
// Close enough to stamp!
|
|
//
|
|
stamp=4; //renav every 4 turns
|
|
|
|
hit_distance = 60;
|
|
|
|
if (!(p_target->Genus.Person->pcom_bent & PCOM_BENT_PLAYERKILL))
|
|
{
|
|
if ( p_person->Genus.Person->PersonType == PERSON_DARCI ||
|
|
(p_person->Genus.Person->pcom_ai == PCOM_AI_COP && p_person->Genus.Person->PersonType==PERSON_COP) ||
|
|
p_person->Genus.Person->pcom_ai == PCOM_AI_COP_DRIVER||
|
|
(p_person->Genus.Person->pcom_ai == PCOM_AI_BODYGUARD && p_person->Genus.Person->PersonType == PERSON_COP))
|
|
|
|
// if (p_person->Genus.Person->pcom_ai == PCOM_AI_COP ||
|
|
// p_person->Genus.Person->pcom_ai == PCOM_AI_COP_DRIVER ||
|
|
// p_person->Genus.Person->PersonType == PERSON_DARCI)
|
|
{
|
|
//
|
|
// Cops get in close enough to arrest!
|
|
//
|
|
|
|
hit_distance = 30;
|
|
p_person->Genus.Person->Agression =0;
|
|
stamp=1; //renav every turn to ensure we get to a good arrest position
|
|
|
|
}
|
|
}
|
|
|
|
p_person->SubState = SUB_STATE_CIRCLING_CIRCLE;
|
|
}
|
|
|
|
if (end == 1)
|
|
{
|
|
|
|
SLONG anim;
|
|
//
|
|
// Carry on with your fighting stance.
|
|
//
|
|
anim=find_idle_fight_stance(p_person);
|
|
|
|
set_anim(p_person, anim);
|
|
}
|
|
|
|
if (p_person->Genus.Person->Agression < -50)
|
|
{
|
|
//
|
|
// back off
|
|
//
|
|
|
|
p_person->SubState=SUB_STATE_CIRCLING_BACK_OFF;
|
|
}
|
|
|
|
/*
|
|
|
|
if(p_person->Genus.Person->Agression>0)
|
|
{
|
|
hit_distance=140;
|
|
}
|
|
|
|
*/
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_CIRCLING_BACK_OFF:
|
|
hit_distance=280;
|
|
if(p_person->Genus.Person->Agression>-10)
|
|
{
|
|
p_person->SubState=SUB_STATE_CIRCLING_CIRCLE;
|
|
//p_person->Genus.Person->Timer1=-5; // make sure I don't push myself
|
|
|
|
//
|
|
// set everyone else to backoff
|
|
//
|
|
if(p_target->Genus.Person->PlayerID)
|
|
process_gang_attack(p_person,p_target);
|
|
|
|
}
|
|
|
|
// FALLTHROUGH!
|
|
|
|
case SUB_STATE_CIRCLING_CIRCLE:
|
|
|
|
if (p_target->Genus.Person->Flags & FLAG_PERSON_DRIVING)
|
|
{
|
|
//
|
|
// Back off from people in cars! If we have a gun then PCOM_process_killing()
|
|
// will make us draw a gun and shoot the car.
|
|
//
|
|
|
|
hit_distance *= 2;
|
|
}
|
|
|
|
if((PTIME(p_person)&1)==0)
|
|
{
|
|
if(p_person->Genus.Person->Agression<0)
|
|
p_person->Genus.Person->Agression+=(GET_SKILL(p_person)>>2)+1;
|
|
else
|
|
p_person->Genus.Person->Agression--;
|
|
}
|
|
|
|
|
|
// if(p_person->Genus.Person->Agression>=0)
|
|
{
|
|
SLONG renav_how_often;
|
|
renav_how_often=(40-(GET_SKILL(p_person)<<1));
|
|
if(!p_target->Genus.Person->PlayerID)
|
|
{
|
|
renav_how_often>>=1;
|
|
if(p_person->Genus.Person->PersonType==PERSON_COP)
|
|
renav_how_often-=5;
|
|
|
|
if(renav_how_often<5)
|
|
renav_how_often=5;
|
|
|
|
}
|
|
if(stamp)
|
|
renav_how_often=stamp;
|
|
if((PTIME(p_person)%renav_how_often)==0)
|
|
{
|
|
if(p_target->Genus.Person->PlayerID)
|
|
{
|
|
//its a player so do the panel stuff
|
|
|
|
track_enemy(p_person);
|
|
}
|
|
|
|
calc_sub_objects_position(p_target,p_target->Draw.Tweened->AnimTween,SUB_OBJECT_PELVIS,&dx,&dy,&dz);
|
|
p_person->Genus.Person->TargetX=(p_target->WorldPos.X>>8)+dx;
|
|
p_person->Genus.Person->TargetZ=(p_target->WorldPos.Z>>8)+dz;
|
|
|
|
|
|
if(p_person->SubState==SUB_STATE_CIRCLING_CIRCLE)
|
|
{
|
|
//
|
|
// set everyone else to backoff
|
|
//
|
|
if(p_target->Genus.Person->PlayerID)
|
|
process_gang_attack(p_person,p_target);
|
|
}
|
|
renav=1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Where is my target relative to me?
|
|
//
|
|
|
|
dx = p_person->Genus.Person->TargetX - (p_person->WorldPos.X >> 8);
|
|
dz = p_person->Genus.Person->TargetZ - (p_person->WorldPos.Z >> 8);
|
|
|
|
dist = QDIST2(abs(dx),abs(dz)) + 1;
|
|
/*
|
|
{
|
|
CBYTE str[100];
|
|
sprintf(str," combat dist %d hit_dist %d \n",dist,hit_distance);
|
|
CONSOLE_text(str);
|
|
}
|
|
*/
|
|
angle = (calc_angle(dx,dz))&2047;
|
|
|
|
dx=0;
|
|
dz=0;
|
|
|
|
//
|
|
// angle relative to targets viewpoint
|
|
//
|
|
|
|
if(dist<hit_distance-15)
|
|
{
|
|
// forewards
|
|
if(bat)
|
|
reqd_anim=ANIM_FIGHT_STEP_N_BAT;
|
|
else
|
|
reqd_anim=ANIM_FIGHT_STEP_N;
|
|
dx=-SIN(angle)>>4;
|
|
dz=-COS(angle)>>4;
|
|
}
|
|
else
|
|
if(dist>hit_distance+15)
|
|
{
|
|
//backwards
|
|
if(bat)
|
|
reqd_anim=ANIM_FIGHT_STEP_S_BAT;
|
|
else
|
|
reqd_anim=ANIM_FIGHT_STEP_S;
|
|
dx=SIN(angle)>>4;
|
|
dz=COS(angle)>>4;
|
|
}
|
|
else
|
|
{
|
|
dx=0;
|
|
dz=0;
|
|
}
|
|
|
|
|
|
// if(dist<hit_distance-20 || dist>hit_distance+20)
|
|
{
|
|
if(p_person->Genus.Person->Timer1++>10)
|
|
{
|
|
SLONG gang;
|
|
void push_into_attack_group_at_angle(Thing *p_person,SLONG gang,SLONG reqd_angle);
|
|
gang=p_target->Genus.Person->GangAttack;
|
|
if(gang==0)
|
|
{
|
|
//CONSOLE_text(" Circling but have no gang");
|
|
set_person_idle(p_person);
|
|
return;
|
|
}
|
|
|
|
remove_from_gang_attack(p_person,p_target);
|
|
push_into_attack_group_at_angle(p_person,gang,(angle+256)>>9);
|
|
p_person->Genus.Person->Timer1=0;
|
|
}
|
|
}
|
|
/*
|
|
else
|
|
if(p_person->SubState==SUB_STATE_CIRCLING_CIRCLE)
|
|
{
|
|
|
|
if(p_person->Genus.Person->Timer1++==15)
|
|
{
|
|
process_gang_attack(p_person,p_target);
|
|
p_person->Genus.Person->Timer1=0;
|
|
}
|
|
}
|
|
*/
|
|
|
|
if (dist > 80)
|
|
{
|
|
//
|
|
// add 1024 to make you look at darci rather than away from darci
|
|
//
|
|
|
|
p_person->Draw.Tweened->Angle = (angle+1024)&2047;
|
|
}
|
|
|
|
dangle=p_person->Genus.Person->AttackAngle<<9;
|
|
// ASSERT(p_person->Genus.Person->AttackAngle==0);
|
|
|
|
dangle-=angle;
|
|
|
|
if(abs(dangle)>30)
|
|
{
|
|
SLONG shift=4;
|
|
if (dangle > 1024) {dangle -= 2048;}
|
|
if (dangle < -1024) {dangle += 2048;}
|
|
|
|
|
|
|
|
if(dangle>0)
|
|
{
|
|
if(reqd_anim==0)
|
|
{
|
|
if(bat)
|
|
reqd_anim=ANIM_FIGHT_STEP_E_BAT;
|
|
else
|
|
reqd_anim=ANIM_FIGHT_STEP_E;
|
|
}
|
|
|
|
angle-=512;
|
|
}
|
|
else
|
|
{
|
|
if(reqd_anim==0)
|
|
{
|
|
if(bat)
|
|
reqd_anim=ANIM_FIGHT_STEP_W_BAT;
|
|
else
|
|
reqd_anim=ANIM_FIGHT_STEP_W;
|
|
}
|
|
angle+=512;
|
|
}
|
|
|
|
angle&=2047;
|
|
if(abs(dangle)<60)
|
|
shift=5;
|
|
dx+=SIN(angle)>>shift;
|
|
dz+=COS(angle)>>shift;
|
|
}
|
|
|
|
if(dx||dz)
|
|
{
|
|
person_normal_move_dxdz(p_person,dx,dz);
|
|
/*
|
|
move_thing(
|
|
dx ,
|
|
0 << 8,
|
|
dz ,
|
|
p_person);
|
|
*/
|
|
|
|
if(reqd_anim)
|
|
if(p_person->Draw.Tweened->CurrentAnim==ANIM_FIGHT || p_person->Draw.Tweened->CurrentAnim==ANIM_BAT_IDLE ||p_person->Draw.Tweened->CurrentAnim==ANIM_KNIFE_FIGHT_READY)
|
|
set_anim(p_person,reqd_anim);
|
|
}
|
|
else
|
|
{
|
|
//if(p_person->Draw.Tweened->CurrentAnim!=ANIM_FIGHT || )
|
|
if(p_person->Draw.Tweened->CurrentAnim!=ANIM_FIGHT && p_person->Draw.Tweened->CurrentAnim!=ANIM_BAT_IDLE && p_person->Draw.Tweened->CurrentAnim!=ANIM_KNIFE_FIGHT_READY)
|
|
{
|
|
SLONG anim;
|
|
anim=find_idle_fight_stance(p_person);
|
|
set_anim(p_person,anim);
|
|
}
|
|
|
|
}
|
|
|
|
if(renav)
|
|
{
|
|
if(am_i_a_thug(p_person))
|
|
{
|
|
//
|
|
// only arrest thugs?
|
|
//
|
|
PCOM_call_cop_to_arrest_me(p_person,1);
|
|
}
|
|
|
|
if (p_target->Genus.Person->PlayerID && EWAY_stop_player_moving())
|
|
{
|
|
//
|
|
// Don't the player while there are stationary in a cutscene.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
if (p_person->Genus.Person->pcom_ai== PCOM_AI_FIGHT_TEST)
|
|
{
|
|
//
|
|
// Fight test dummies never throw a punch.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
extern void PCOM_set_person_move_punch (Thing *p_person);
|
|
extern void PCOM_set_person_move_kick (Thing *p_person);
|
|
extern void PCOM_set_person_move_arrest(Thing *p_person);
|
|
|
|
kick_or_punch++;
|
|
// if(p_target->Genus.Person->Flags&FLAG_PERSON_KO)
|
|
if(is_person_ko_and_lay_down(p_target))
|
|
{
|
|
if (!(p_target->Genus.Person->pcom_bent & PCOM_BENT_PLAYERKILL))
|
|
{
|
|
if ( p_person->Genus.Person->PersonType == PERSON_DARCI ||
|
|
(p_person->Genus.Person->pcom_ai == PCOM_AI_COP && p_person->Genus.Person->PersonType==PERSON_COP) ||
|
|
p_person->Genus.Person->pcom_ai == PCOM_AI_COP_DRIVER||
|
|
(p_person->Genus.Person->pcom_ai == PCOM_AI_BODYGUARD && p_person->Genus.Person->PersonType == PERSON_COP))
|
|
{
|
|
if(dist<50)
|
|
PCOM_set_person_move_arrest(p_person);
|
|
}
|
|
else
|
|
{
|
|
PCOM_set_person_move_kick(p_person);
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
else
|
|
if (p_target->SubState == SUB_STATE_GRAPPLE_HELD &&
|
|
p_person->Genus.Person->pcom_ai == PCOM_AI_COP)
|
|
{
|
|
//
|
|
// Cops always throw their grapplee's so they can arrest them!
|
|
//
|
|
|
|
PCOM_set_person_move_punch(p_person);
|
|
}
|
|
*/
|
|
else
|
|
if(dist<160 && dist>90)
|
|
{
|
|
|
|
if(kick_or_punch&1)
|
|
{
|
|
PCOM_set_person_move_punch(p_person);
|
|
}
|
|
else
|
|
{
|
|
PCOM_set_person_move_kick(p_person);
|
|
}
|
|
|
|
}
|
|
else
|
|
if(dist<90)
|
|
{
|
|
PCOM_set_person_move_punch(p_person);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifndef PSX
|
|
void fn_person_circle_old(Thing *p_person)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG end;
|
|
SLONG dist;
|
|
SLONG angle;
|
|
SLONG shove;
|
|
SLONG dangle;
|
|
SLONG random;
|
|
SLONG ddist;
|
|
|
|
SLONG vx = 0;
|
|
SLONG vz = 0;
|
|
|
|
Thing *p_target = TO_THING(p_person->Genus.Person->Target);
|
|
|
|
end = person_normal_animate(p_person);
|
|
|
|
if (end == 1)
|
|
{
|
|
//
|
|
// Carry on with your fighting stance.
|
|
//
|
|
|
|
set_anim(p_person, ANIM_FIGHT);
|
|
}
|
|
|
|
//
|
|
// Where is our target relative to us?
|
|
//
|
|
|
|
dx = p_target->WorldPos.X - p_person->WorldPos.X >> 8;
|
|
dz = p_target->WorldPos.Z - p_person->WorldPos.Z >> 8;
|
|
|
|
dist = QDIST2(abs(dx),abs(dz)) + 1;
|
|
angle = calc_angle(dx,dz) + 1024;
|
|
angle &= 2047;
|
|
dangle = angle_diff(angle, p_person->Draw.Tweened->Angle);
|
|
|
|
//
|
|
// Trickle round to 90 degree relative angle.
|
|
//
|
|
|
|
dangle += 256;
|
|
dangle &= 0xff;
|
|
|
|
shove = p_person->Genus.Person->Shove;
|
|
shove += dangle - 256 >> 4;
|
|
|
|
SATURATE(shove, -127, +127);
|
|
|
|
if (shove > 0) {shove -= 16;} else {shove += 16;}
|
|
|
|
p_person->Genus.Person->Shove = shove;
|
|
|
|
//
|
|
// The distance we hop by.
|
|
//
|
|
|
|
dx = ((0x10 * TICK_RATIO) * dx) / dist;
|
|
dz = ((0x10 * TICK_RATIO) * dz) / dist;
|
|
|
|
dx >>= TICK_SHIFT;
|
|
dz >>= TICK_SHIFT;
|
|
|
|
//
|
|
// Should we hop to the left or right?
|
|
//
|
|
|
|
if (shove > 0)
|
|
{
|
|
random = Random() & 0x7f;
|
|
|
|
if (shove > random)
|
|
{
|
|
//
|
|
// Hop to the left.
|
|
//
|
|
|
|
vx += -dz;
|
|
vz += +dx;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
random = Random() & 0x7f;
|
|
random = -random;
|
|
|
|
if (shove < random)
|
|
{
|
|
//
|
|
// Hop to the right.
|
|
//
|
|
|
|
vx += +dz;
|
|
vz += -dx;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Should we hop in or out?
|
|
//
|
|
|
|
ddist = dist - 0x80;
|
|
|
|
if (ddist > 0)
|
|
{
|
|
random = Random() & 0x3f;
|
|
|
|
if (ddist > random)
|
|
{
|
|
vx += dx;
|
|
vz += dz;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
random = Random() & 0x3f;
|
|
random = -random;
|
|
|
|
if (ddist < random)
|
|
{
|
|
vx += -dx;
|
|
vz += -dz;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Move the person.
|
|
//
|
|
|
|
move_thing(
|
|
vx << 8,
|
|
0 << 8,
|
|
vz << 8,
|
|
p_person);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
//*************************************************************************************************************
|
|
//** (JCL) - get person scale
|
|
|
|
SLONG person_get_scale(Thing *t)
|
|
{
|
|
// ASSERT( t is actually a person. probably is, cause this gets called from FIGURE_draw_blah() );
|
|
|
|
// fixed point 8. (ie 256 = normal, 512 = double size, 128 = half size.
|
|
// I wonder what happens if you use negative values!
|
|
|
|
if(t->Class==CLASS_PERSON && t->Genus.Person->PersonType==PERSON_ROPER)
|
|
return(276);
|
|
if(t->Class==CLASS_PERSON && t->Genus.Person->PlayerID)
|
|
{
|
|
return(256);
|
|
}
|
|
else
|
|
{
|
|
// if(t->Class==CLASS_BAT && t->Genus.Bat->type==BAT_TYPE_BALROG)
|
|
// return(256);
|
|
// else
|
|
// return 256;//56;
|
|
|
|
return(256);//250+(THING_NUMBER(t)&0x1f));
|
|
}
|
|
|
|
// this essentially generates random heights per person
|
|
//return ((SLONG(t) >> 3) & 7) * (384 / 7) + 128;
|
|
|
|
// PS - this function should be reasonably quick. it's called 15 times per character per frame.
|
|
}
|
|
|
|
|
|
//
|
|
// returns how many game_turns an anim takes, a game_turn is assumed to be 1/20th of a second
|
|
//
|
|
#ifndef PSX
|
|
SLONG how_long_is_anim(SLONG anim)
|
|
{
|
|
GameKeyFrame *frame;
|
|
SLONG total=0;
|
|
|
|
frame=global_anim_array[0][anim];
|
|
|
|
|
|
while(frame)
|
|
{
|
|
SLONG step;
|
|
|
|
step=frame->TweenStep;
|
|
if(!step)
|
|
step=1;
|
|
|
|
|
|
total+=256/step;
|
|
if(frame->Flags&ANIM_FLAG_LAST_FRAME)
|
|
break;
|
|
|
|
frame = frame->NextFrame;
|
|
}
|
|
return(total);
|
|
|
|
}
|
|
#endif
|
|
|
|
SLONG person_ok_for_conversation(Thing *p_person)
|
|
{
|
|
if (p_person->Class != CLASS_PERSON)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if(is_person_ko(p_person))
|
|
return(0);
|
|
|
|
if(p_person->State==STATE_DEAD)
|
|
return(0);
|
|
if(p_person->State==STATE_DANGLING)
|
|
return(0);
|
|
if(p_person->State==STATE_DYING)
|
|
return(0);
|
|
if(p_person->State==STATE_JUMPING)
|
|
return(0);
|
|
|
|
if (p_person->State == STATE_CLIMB_LADDER)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if ((p_person->Genus.Person->Flags & FLAG_PERSON_DRIVING) ||
|
|
(p_person->Genus.Person->Flags & FLAG_PERSON_BIKING))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
void set_person_float_up(Thing *p_person)
|
|
{
|
|
set_generic_person_state_function(p_person, STATE_FLOAT);
|
|
|
|
p_person->SubState = SUB_STATE_FLOAT_UP;
|
|
|
|
// set_anim(p_person, ANIM_DANCE_HEADBANG);
|
|
}
|
|
|
|
void set_person_float_down(Thing *p_person)
|
|
{
|
|
ASSERT(p_person->State == STATE_FLOAT);
|
|
|
|
p_person->SubState = SUB_STATE_FLOAT_DOWN;
|
|
}
|
|
|
|
|
|
void fn_person_float(Thing *p_person)
|
|
{
|
|
SLONG ground;
|
|
|
|
ground = PAP_calc_map_height_at(
|
|
p_person->WorldPos.X >> 8,
|
|
p_person->WorldPos.Z >> 8);
|
|
|
|
switch(p_person->SubState)
|
|
{
|
|
case SUB_STATE_FLOAT_UP:
|
|
|
|
p_person->WorldPos.Y += 64 * TICK_RATIO >> TICK_SHIFT;
|
|
p_person->Draw.Tweened->Tilt = (-p_person->WorldPos.Y >> 8) - ground;
|
|
|
|
if (p_person->Draw.Tweened->Tilt < -200)
|
|
{
|
|
p_person->SubState = SUB_STATE_FLOAT_BOB;
|
|
}
|
|
|
|
break;
|
|
|
|
case SUB_STATE_FLOAT_BOB:
|
|
|
|
//
|
|
// Do nowt while bobbing...
|
|
//
|
|
|
|
break;
|
|
|
|
case SUB_STATE_FLOAT_DOWN:
|
|
|
|
p_person->WorldPos.Y -= 64 * TICK_RATIO >> TICK_SHIFT;
|
|
p_person->Draw.Tweened->Tilt = (-p_person->WorldPos.Y >> 8) - ground;
|
|
|
|
if (p_person->Draw.Tweened->Tilt > -4)
|
|
{
|
|
set_person_idle(p_person);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void set_person_injured(Thing *p_person)
|
|
{
|
|
set_generic_person_state_function(p_person, STATE_DEAD);
|
|
set_anim(p_person, ANIM_INJURED_LOOP);
|
|
p_person->SubState = SUB_STATE_DEAD_INJURED;
|
|
p_person->Genus.Person->Timer1 = 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Makes sure that person 'a' is at least half a block from person 'b'.
|
|
//
|
|
|
|
void push_people_apart(Thing *p_person, Thing *p_avoid)
|
|
{
|
|
SLONG dx;
|
|
SLONG dz;
|
|
SLONG dist;
|
|
|
|
if (p_person->Genus.Person->Ware ||
|
|
p_avoid ->Genus.Person->Ware)
|
|
{
|
|
//
|
|
// This function doesn't work for people in warehouses.
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
dx = p_person->WorldPos.X - p_avoid->WorldPos.X >> 8;
|
|
dz = p_person->WorldPos.Z - p_avoid->WorldPos.Z >> 8;
|
|
|
|
dist = QDIST2(abs(dx),abs(dz)) + 1;
|
|
|
|
if (dist >= 0x80)
|
|
{
|
|
//
|
|
// Already far enough apart.
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
SLONG new_x = (p_person->WorldPos.X >> 8) + dx * (0x80 - dist) / dist;
|
|
SLONG new_z = (p_person->WorldPos.Z >> 8) + dz * (0x80 - dist) / dist;
|
|
|
|
SLONG old_y = PAP_calc_map_height_at(p_person->WorldPos.X >> 8, p_person->WorldPos.Z >> 8);
|
|
SLONG new_y = PAP_calc_map_height_at(new_x, new_z);
|
|
|
|
if (abs(old_y - new_y) < 0x50)
|
|
{
|
|
//
|
|
// Ok to move here...
|
|
//
|
|
|
|
GameCoord newpos;
|
|
|
|
newpos.X = new_x << 8;
|
|
newpos.Y = new_y << 8;
|
|
newpos.Z = new_z << 8;
|
|
|
|
move_thing_on_map(p_person, &newpos);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Bugger it! Doesn't have to work all the time...
|
|
//
|
|
}
|
|
}
|