implement various fixes and refactorings

master
an 2019-09-21 15:29:42 -04:00
parent 8d8a46d259
commit e6221792a4
40 changed files with 560 additions and 543 deletions

BIN
maps/fiend_test.bsp Normal file

Binary file not shown.

BIN
maps/fiend_test.lit Normal file

Binary file not shown.

View File

@ -1,38 +1,38 @@
progs.dat
source/defs.qc
source/common.qc
source/fight.qc
source/subs.qc
source/c_defs.qc
source/c_common.qc
source/c_combat.qc
source/ai.qc
source/buttons.qc
source/client.qc
source/combat.qc
source/doors.qc
source/items.qc
source/misc.qc
source/monsters.qc
source/plats.qc
source/player.qc
source/triggers.qc
source/weapons.qc
source/world.qc
source/ai_fight.qc
source/ai_monsters.qc
source/ai_subs.qc
source/boss.qc
source/demon.qc
source/dog.qc
source/knight.qc
source/ogre.qc
source/shambler.qc
source/soldier.qc
source/wizard.qc
source/zombie.qc
source/p_client.qc
source/p_player.qc
source/p_weapons.qc
source/enforcer.qc
source/fish.qc
source/hknight.qc
source/oldone.qc
source/shalrath.qc
source/tarbaby.qc
source/w_buttons.qc
source/w_doors.qc
source/w_items.qc
source/w_misc.qc
source/w_plats.qc
source/w_triggers.qc
source/w_world.qc
source/m_army.qc
source/m_boss.qc
source/m_demon.qc
source/m_dog.qc
source/m_enforcer.qc
source/m_fish.qc
source/m_hknight.qc
source/m_knight.qc
source/m_ogre.qc
source/m_oldone.qc
source/m_shalrath.qc
source/m_shambler.qc
source/m_tarbaby.qc
source/m_wizard.qc
source/m_zombie.qc

View File

@ -38,24 +38,6 @@ The number of seconds to spend standing or bowing for path_stand or path_bow
==============================================================================
*/
void() movetarget_f = {
if(!self.targetname) {
error_obj("monster_movetarget: no targetname");
}
self.solid = SOLID_TRIGGER;
self.touch = t_movetarget;
set_size(self, '-8 -8 -8', '8 8 8');
};
/*QUAKED path_corner(0.5 0.3 0) (-8 -8 -8) (8 8 8)
Monsters will continue walking towards the next target corner.
*/
void() path_corner = {
movetarget_f();
};
/*
=============
t_movetarget
@ -83,7 +65,6 @@ void() t_movetarget = {
sound(self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE); // play chainsaw drag sound
}
//print_dbg("t_movetarget\n");
self.goalentity = self.movetarget = find(world, targetname, other.target);
self.ideal_yaw = vec_yaw(self.goalentity.origin - self.origin);
if(!self.movetarget) {
@ -93,6 +74,24 @@ void() t_movetarget = {
}
};
void() movetarget_f = {
if(!self.targetname) {
error_obj("monster_movetarget: no targetname");
}
self.solid = SOLID_TRIGGER;
self.touch = t_movetarget;
set_size(self, '-8 -8 -8', '8 8 8');
};
/*QUAKED path_corner(0.5 0.3 0) (-8 -8 -8) (8 8 8)
Monsters will continue walking towards the next target corner.
*/
void() path_corner = {
movetarget_f();
};
//============================================================================
@ -324,32 +323,6 @@ void() ai_turn = {
//=============================================================================
/*
=============
choose_turn
=============
*/
void(vector dest3) choose_turn = {
vector dir, newdir;
dir = self.origin - dest3;
newdir_x = trace_plane_normal_y;
newdir_y = 0 - trace_plane_normal_x;
newdir_z = 0;
if(dir * newdir > 0) {
dir_x = 0 - trace_plane_normal_y;
dir_y = trace_plane_normal_x;
} else {
dir_x = trace_plane_normal_y;
dir_y = 0 - trace_plane_normal_x;
}
dir_z = 0;
self.ideal_yaw = vec_yaw(dir);
};
/*
============
facing_ideal

View File

@ -1,4 +1,4 @@
// fight.qc: monster attack functions
// ai_fight.qc: monster attack functions
/*
@ -9,19 +9,6 @@ When it decides it can't attack, it goes into hunt mode.
*/
void() knight_attack = {
float len;
// decide if now is a good swing time
len = vec_len(self.enemy.origin + self.enemy.view_ofs - (self.origin + self.view_ofs));
if(len < 80) {
knight_atk1();
} else {
knight_runatk1();
}
};
//=============================================================================
/*
@ -185,7 +172,7 @@ void() ai_melee_side = {
if(vec_len(delta) > 60) {
return;
}
if(!can_damage(self.enemy, self)) {
if(!ent_can_damage(self.enemy, self)) {
return;
}
ldmg = (random() + random() + random()) * 3;

View File

@ -1,4 +1,4 @@
// monsters.qc: basic monster functions
// ai_monsters.qc: basic monster functions
/* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */
@ -12,6 +12,11 @@
// <code>
// };
float() enemy_is_high = {
return !self.enemy ||
fabs(self.enemy.origin_z - self.origin_z) >= AI_MONSTER_HIGH;
};
/*
================
monster_use
@ -113,13 +118,13 @@ void() walkmonster_start_go = {
}
// spread think times so they don't all happen at same time
self.nextthink = self.nextthink + random() * 0.5;
self.nextthink = time + 0.1 + random() * 0.5;
};
void() walkmonster_start = {
// delay drop to floor to make sure all doors have been spawned
// spread think times so they don't all happen at same time
self.nextthink = self.nextthink + random() * 0.5;
self.nextthink = time + 0.1 + random() * 0.5;
self.think = walkmonster_start_go;
total_monsters = total_monsters + 1;
};
@ -158,11 +163,13 @@ void() flymonster_start_go = {
self.pausetime = 99999999;
self.th_stand();
}
self.nextthink = time + 0.1 + random() * 0.5;
};
void() flymonster_start = {
// spread think times so they don't all happen at same time
self.nextthink = self.nextthink + random() * 0.5;
self.flags |= FL_FLY;
self.nextthink = time + 0.1 + random() * 0.5;
self.think = flymonster_start_go;
total_monsters = total_monsters + 1;
};
@ -174,7 +181,6 @@ void() swimmonster_start_go = {
}
self.takedamage = DAMAGE_AIM;
total_monsters = total_monsters + 1;
self.ideal_yaw = self.angles * '0 1 0';
if(!self.yaw_speed) {
@ -200,12 +206,13 @@ void() swimmonster_start_go = {
}
// spread think times so they don't all happen at same time
self.nextthink = self.nextthink + random() * 0.5;
self.nextthink = time + 0.1 + random() * 0.5;
};
void() swimmonster_start = {
// spread think times so they don't all happen at same time
self.nextthink = self.nextthink + random() * 0.5;
self.flags |= FL_SWIM;
self.nextthink = time + 0.1 + random() * 0.5;
self.think = swimmonster_start_go;
total_monsters = total_monsters + 1;
};

View File

@ -1,4 +1,4 @@
// subs.qc: subroutines for think frames
// ai_subs.qc: subroutines for think frames
void() sub_null = {};
void(entity attacker, float damage) sub_pain_null = {};

View File

@ -1,4 +1,4 @@
// combat.qc: entity-entity damage functions
// c_combat.qc: entity-entity damage functions
float(entity targ, entity attacker) is_same_team = {
return targ != attacker &&
@ -14,13 +14,13 @@ float(entity targ, entity attacker) are_both_players = {
/*
============
can_damage
ent_can_damage
Returns true if the inflictor can directly damage the target. Used for
explosions and melee attacks.
============
*/
float(entity targ, entity inflictor) can_damage = {
float(entity targ, entity inflictor) ent_can_damage = {
// bmodels need special checking because their origin is 0,0,0
if(targ.movetype == MOVETYPE_PUSH) {
trace_line(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
@ -219,35 +219,39 @@ void(entity inflictor, entity attacker, float damage, entity ignore) ent_radius_
float points;
entity head;
vector org;
float attacker_damaged;
float attacker_points;
head = find_radius(inflictor.origin, damage + 40);
while(head) {
if(head != ignore) {
if(head.takedamage) {
org = head.origin + (head.mins + head.maxs) * 0.5;
points = 0.5 * vec_len(inflictor.origin - org);
if(points < 0) {
points = 0;
}
points = damage - points;
if(head == attacker) {
points = points * 0.5;
}
if(points > 0) {
if(can_damage(head, inflictor)) {
// shambler takes half damage from all explosions
if(head.classname == "monster_shambler") {
ent_damage(head, inflictor, attacker, points * 0.5);
} else {
ent_damage(head, inflictor, attacker, points);
}
if(head != ignore && head.takedamage) {
org = head.origin + (head.mins + head.maxs) * 0.5;
points = 0.5 * vec_len(inflictor.origin - org);
if(points < 0) {
points = 0;
}
points = damage - points;
if(points > 0 && ent_can_damage(head, inflictor)) {
if(head != attacker) {
// shambler takes half damage from all explosions
if(head.classname == "monster_shambler") {
ent_damage(head, inflictor, attacker, points * 0.5);
} else {
ent_damage(head, inflictor, attacker, points);
}
} else {
attacker_damaged = TRUE;
attacker_points = points * 0.5;
}
}
}
head = head.chain;
}
if(attacker_damaged) {
ent_damage(attacker, inflictor, attacker, attacker_points);
}
};
/*
@ -272,7 +276,7 @@ void(entity attacker, float damage) beam_damage = {
points = points * 0.5;
}
if(points > 0) {
if(can_damage(head, attacker)) {
if(ent_can_damage(head, attacker)) {
if(head.classname == "monster_shambler") {
ent_damage(head, attacker, attacker, points * 0.5);
} else {

View File

@ -1,4 +1,4 @@
// common.qc: common functions
// c_common.qc: common functions
const float PO2_LUT[25] = {
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768,
@ -42,16 +42,15 @@ float(entity targ) range = {
spot2 = targ.origin + targ.view_ofs;
r = vec_len(spot1 - spot2);
if(r < 120) {
if(r < AI_RANGE_MELEE) {
return RANGE_MELEE;
}
if(r < 500) {
} else if(r < AI_RANGE_NEAR) {
return RANGE_NEAR;
}
if(r < 1000) {
} else if(r < AI_RANGE_MID) {
return RANGE_MID;
} else {
return RANGE_FAR;
}
return RANGE_FAR;
};
// returns 1 if the entity is visible to self, even if not infront()

View File

@ -1,4 +1,4 @@
// defs.qc: global definitions
// c_defs.qc: global definitions
// system globals ------------------------------------------------------------|
#pragma noref 1
@ -417,13 +417,41 @@ enum {
// protocol bytes
enum {
SVC_TEMPENTITY = 23,
SVC_KILLEDMONSTER = 27,
SVC_FOUNDSECRET = 28,
SVC_INTERMISSION = 30,
SVC_FINALE = 31,
SVC_CDTRACK = 32,
SVC_SELLSCREEN = 33,
SVC_BAD,
SVC_NOP,
SVC_DISCONNECT,
SVC_UPDATESTAT,
SVC_VERSION,
SVC_SETVIEW,
SVC_SOUND,
SVC_TIME,
SVC_PRINT,
SVC_STUFFTEXT,
SVC_SETANGLE,
SVC_SERVERINFO,
SVC_LIGHTSTYLE,
SVC_UPDATENAME,
SVC_UPDATEFRAGS,
SVC_CLIENTDATA,
SVC_STOPSOUND,
SVC_UPDATECOLORS,
SVC_PARTICLE,
SVC_DAMAGE,
SVC_SPAWNSTATIC,
SVC_SPAWNBINARY,
SVC_SPAWNBASELINE,
SVC_TEMPENTITY,
SVC_SETPAUSE,
SVC_SIGNONNUM,
SVC_CENTERPRINT,
SVC_KILLEDMONSTER,
SVC_FOUNDSECRET,
SVC_SPAWNSTATICSOUND,
SVC_INTERMISSION,
SVC_FINALE,
SVC_CDTRACK,
SVC_SELLSCREEN,
SVC_CUTSCENE,
};
enum {
@ -573,6 +601,13 @@ enum {
CHANGELEVEL_NO_INTERMISSION = 1,
};
enum {
AI_RANGE_MELEE = 120,
AI_RANGE_NEAR = 500,
AI_RANGE_MID = 1000,
AI_MONSTER_HIGH = 48,
};
// super co-op additions
enum {
PRO_NONE,
@ -791,171 +826,98 @@ float ext_strings;
.float lives;
.float spectating;
.float hurt_together_time;
.float hurt_nextthink;
// functions -----------------------------------------------------------------|
void(float normal) sub_attack_finished;
void(vector tdest, float tspeed, void() func) sub_calc_move;
void(entity ent, vector tdest, float tspeed, void() func) sub_calc_move_ent;
void(vector destangle, float tspeed, void() func) sub_calc_angle_move;
void() sub_calc_move_done;
void() sub_calc_angle_move_done;
void(void() thinkst) sub_check_refire;
void() sub_calc_move_done;
void() sub_null;
void(entity attacker, float damage) sub_pain_null;
void() sub_use_targets;
void() sub_remove;
void() sub_use_targets;
void(entity attacker, float damage) sub_pain_null;
void(entity ent, vector tdest, float tspeed, void() func) sub_calc_move_ent;
void(float normal) sub_attack_finished;
void(vector destangle, float tspeed, void() func) sub_calc_angle_move;
void(vector tdest, float tspeed, void() func) sub_calc_move;
void(void() thinkst) sub_check_refire;
float() check_attack;
void() found_target;
entity() drop_backpack;
float(entity e, float healamount, float ignore) ent_heal;
float(entity targ, entity inflictor) can_damage;
float(entity targ, entity inflictor) ent_can_damage;
void() ent_missile_touch;
void(entity bomb, entity attacker, float rad, entity ignore) ent_radius_damage;
void(entity targ, entity inflictor, entity attacker, float damage) ent_damage;
void(float wep) wep_change_weapon;
void() wep_cycle_weapon_reverse;
void() wep_cycle_weapon;
void() wep_fire_axe;
void() wep_fire_shotgun;
void() wep_fire_super_shotgun;
void() wep_fire_rocket;
void() wep_fire_lightning;
void() wep_fire_grenade;
void(float ox) wep_fire_nail;
void() wep_fire_super_nail;
float() wep_best_weapon;
void() wep_cycle_weapon;
void() wep_cycle_weapon_reverse;
void() wep_fire_axe;
void() wep_fire_grenade;
void() wep_fire_lightning;
void() wep_fire_rocket;
void() wep_fire_shotgun;
void() wep_fire_super_nail;
void() wep_fire_super_shotgun;
void() wep_set_current_ammo;
void() wep_weapon_frame;
void(float ox) wep_fire_nail;
void(float wep) wep_change_weapon;
string() key_1_name;
string() key_2_name;
string() key_1_name, key_2_name;
void() army_fire;
float() army_check_attack;
float() demon_check_attack;
void() demon_jump_touch;
void(float side) demon_melee;
float() dog_check_attack;
void() dog_leap1;
void() dog_run1;
void() shalrath_home;
void() shalrath_missile;
void() shalrath_missile_touch;
float(entity targ, entity attacker) is_same_team;
void() decode_level_parms;
void(entity ent) copy_to_body_queue;
void() init_body_queue;
void() super_damage_sound;
void() ai_face;
void() armor_touch;
void() bubble_bob;
void() bubble_remove;
void() button_return;
void() button_wait;
void() door_go_down;
void() door_go_up;
void() fd_secret_done;
void() fd_secret_move1;
void() fd_secret_move2;
void() fd_secret_move3;
void() fd_secret_move4;
void() fd_secret_move5;
void() fd_secret_move6;
void() finale_1;
void() finale_2;
void() finale_3;
void() finale_4;
void() fire_fly;
void() fire_touch;
void() health_touch;
void() item_megahealth_rot;
void() make_bubbles;
void() monster_death_use;
void() movetarget_f;
void() powerup_touch;
void() set_suicide_frame;
void(vector org, vector dir) launch_spike;
void() spike_touch;
void() superspike_touch;
void() swimmonster_start;
void() t_movetarget;
void() train_next;
void() swimmonster_start;
void(entity targ, entity attacker) client_obituary;
void(float num_bubbles) death_bubbles;
void(vector dest) choose_turn;
void(vector org, vector vec) launch_laser;
void(vector org, vector vel, float damage) spawn_blood;
void() become_explosion;
void() hknight_char_a1;
void() hknight_run1;
void() ogre_smash1;
void() ogre_swing1;
float() army_check_attack;
float() demon_check_attack;
float() dog_check_attack;
float() ogre_check_attack;
float() sham_check_attack;
float() wiz_check_attack;
void() plat_center_touch;
void() plat_crush;
void() plat_go_down;
void() plat_go_up;
void() plat_outside_touch;
void() plat_trigger_use;
void() knight_attack;
void() knight_atk1;
void() knight_bow1;
void() knight_bow6;
void() knight_runatk1;
void() knight_walk1;
void() player_die;
void() player_axe1;
void() player_axeb1;
void() player_axec1;
void() player_axed1;
void() player_die_ax1;
void() player_diea1;
void() player_dieb1;
void() player_diec1;
void() player_died1;
void() player_diee1;
void() player_die;
void() player_light1;
void() player_nail1;
void(entity attacker, float damage) player_pain;
void() player_rocket1;
void() player_run;
void() player_run;
void() player_shot1;
void() player_stand1;
void() sham_smash1;
void() sham_swingl1;
void() sham_swingr1;
void() sham_swingr1;
float() sham_check_attack;
void() tbaby_jump1;
void() tbaby_jump5;
float() wiz_check_attack;
void() wiz_run1;
void() wiz_side1;
void(entity attacker, float damage) player_pain;
void(vector org) spawn_tfog;
void(vector org, entity death_owner) spawn_tdeath;
void() info_player_start;
void() func_train_find;
void(vector p) boss_missile;
void() impulse_commands;
// EOF

View File

@ -1,4 +1,4 @@
// soldier.qc: Grunt
// m_army.qc: Grunt
$cd id1 / models / soldier3
$origin 0 - 6 24
@ -31,6 +31,8 @@ $frame prowl_1 prowl_2 prowl_3 prowl_4 prowl_5 prowl_6 prowl_7 prowl_8
$frame prowl_9 prowl_10 prowl_11 prowl_12 prowl_13 prowl_14 prowl_15 prowl_16
$frame prowl_17 prowl_18 prowl_19 prowl_20 prowl_21 prowl_22 prowl_23 prowl_24
void() army_fire;
//=============================================================================
/*

View File

@ -1,4 +1,4 @@
// boss.qc: Chthon, boss of E1
// m_boss.qc: Chthon, boss of E1
$cd id1 / models / boss1
$origin 0 0 - 15
@ -29,6 +29,8 @@ $frame shockb1 shockb2 shockb3 shockb4 shockb5 shockb6
$frame shockc1 shockc2 shockc3 shockc4 shockc5 shockc6 shockc7 shockc8
$frame shockc9 shockc10
void(vector p) boss_missile;
void() boss_face = {
// go for another player if multi player
if(enemy_is_gone(self.enemy) || random() < 0.02) {
@ -174,7 +176,7 @@ void() boss_death9 = [$death9, boss_death10] {
void() boss_death10 = [$death9, boss_death10] {
killed_monsters = killed_monsters + 1;
write_byte(MSG_ALL, SVC_KILLEDMONSTER); // FIXME: reliable broadcast
write_byte(MSG_ALL, SVC_KILLEDMONSTER);
sub_use_targets();
remove(self);
};

View File

@ -1,4 +1,4 @@
// demon.qc: Fiend
// m_demon.qc: Fiend
$cd id1 / models / demon3
$scale 0.8
@ -23,6 +23,9 @@ $frame death1 death2 death3 death4 death5 death6 death7 death8 death9
$frame attacka1 attacka2 attacka3 attacka4 attacka5 attacka6 attacka7 attacka8
$frame attacka9 attacka10 attacka11 attacka12 attacka13 attacka14 attacka15
void() demon_jump_touch;
void(float side) demon_melee;
//============================================================================
void() demon1_stand1 = [ $stand1, demon1_stand2 ] {ai_stand();};
@ -219,12 +222,12 @@ Returns TRUE if a melee attack would hit right now
==============
*/
float() demon_check_melee = {
if(enemy_range == RANGE_MELEE) {
// FIXME: check canreach
if(enemy_range == RANGE_MELEE && !enemy_is_high()) {
self.attack_state = AS_MELEE;
return TRUE;
} else {
return FALSE;
}
return FALSE;
};
/*
@ -237,13 +240,10 @@ float() demon_check_jump = {
vector dist;
float d;
if(self.origin_z + self.mins_z > self.enemy.origin_z + self.enemy.mins_z
+ 0.75 * self.enemy.size_z) {
return FALSE;
}
if(self.origin_z + self.maxs_z < self.enemy.origin_z + self.enemy.mins_z
+ 0.25 * self.enemy.size_z) {
if(self.origin_z + self.mins_z >
self.enemy.origin_z + self.enemy.mins_z + 0.75 * self.enemy.size_z ||
self.origin_z + self.maxs_z <
self.enemy.origin_z + self.enemy.mins_z + 0.25 * self.enemy.size_z) {
return FALSE;
}
@ -252,17 +252,7 @@ float() demon_check_jump = {
d = vec_len(dist);
if(d < 100) {
return FALSE;
}
if(d > 200) {
if(random() < 0.9) {
return FALSE;
}
}
return TRUE;
return !(d < 100 || (d > 200 && random() < 0.9));
};
float() demon_check_attack = {
@ -297,7 +287,7 @@ void(float side) demon_melee = {
if(vec_len(delta) > 100) {
return;
}
if(!can_damage(self.enemy, self)) {
if(!ent_can_damage(self.enemy, self)) {
return;
}

View File

@ -1,4 +1,4 @@
// dog.qc: Rottweiler
// m_dog.qc: Rottweiler
$cd id1 / models / dog
$origin 0 0 24
@ -25,6 +25,8 @@ $frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8
void() dog_leap1, dog_run1;
/*
================
dog_bite
@ -41,7 +43,7 @@ void() dog_bite = {
ai_charge(10);
if(!can_damage(self.enemy, self)) {
if(!ent_can_damage(self.enemy, self)) {
return;
}
@ -250,12 +252,12 @@ Returns TRUE if a melee attack would hit right now
==============
*/
float() dog_check_melee = {
if(enemy_range == RANGE_MELEE) {
// FIXME: check canreach
if(enemy_range == RANGE_MELEE && !enemy_is_high()) {
self.attack_state = AS_MELEE;
return TRUE;
} else {
return FALSE;
}
return FALSE;
};
/*

View File

@ -1,4 +1,4 @@
// enforcer.qc: Enforcer
// m_enforcer.qc: Enforcer
$cd id1 / models / enforcer
$origin 0 - 6 24

View File

@ -1,4 +1,4 @@
// fish.qc: Rotfish
// m_fish.qc: Rotfish
$cd id1 / models / fish
$origin 0 0 24
@ -114,7 +114,7 @@ void() f_death1 = [ $death1, f_death2 ] {
sound(self, CHAN_VOICE, "fish/death.wav", 1, ATTN_NORM);
};
void() f_death2 = [ $death2, f_death3 ] {};
void() f_death3 = [ $death3, f_death4 ] {};
void() f_death3 = [ $death3, f_death4 ] {self.solid = SOLID_NOT;};
void() f_death4 = [ $death4, f_death5 ] {};
void() f_death5 = [ $death5, f_death6 ] {};
void() f_death6 = [ $death6, f_death7 ] {};
@ -132,7 +132,7 @@ void() f_death17 = [ $death17, f_death18 ] {};
void() f_death18 = [ $death18, f_death19 ] {};
void() f_death19 = [ $death19, f_death20 ] {};
void() f_death20 = [ $death20, f_death21 ] {};
void() f_death21 = [ $death21, f_death21 ] {self.solid = SOLID_NOT;};
void() f_death21 = [ $death21, f_death21 ] {};
void() f_pain1 = [ $pain1, f_pain2 ] {};
void() f_pain2 = [ $pain2, f_pain3 ] {ai_pain(6);};
@ -145,11 +145,20 @@ void() f_pain8 = [ $pain8, f_pain9 ] {ai_pain(6);};
void() f_pain9 = [ $pain9, f_run1 ] {ai_pain(6);};
void(entity attacker, float damage) fish_pain = {
// fish allways do pain frames
f_pain1();
};
void() f_die = {
if(self.health < -35) {
sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM);
throw_head("progs/gib3.mdl", self.health);
throw_gib("progs/gib3.mdl", self.health);
return;
}
f_death1();
};
/*QUAKED monster_fish(1 0 0) (-16 -16 -24) (16 16 24) Ambush
*/
@ -175,7 +184,7 @@ void() monster_fish = {
self.th_stand = f_stand1;
self.th_walk = f_walk1;
self.th_run = f_run1;
self.th_die = f_death1;
self.th_die = f_die;
self.th_pain = fish_pain;
self.th_melee = f_attack1;

View File

@ -1,4 +1,4 @@
// hknight.qc: Death Knight
// m_hknight.qc: Death Knight
$cd id1 / models / knight2
$origin 0 0 24
@ -45,6 +45,8 @@ $frame w_attack21 w_attack22
$frame magicc1 magicc2 magicc3 magicc4 magicc5 magicc6 magicc7 magicc8
$frame magicc9 magicc10 magicc11
void() hknight_char_a1, hknight_run1;
void() hknight_idle_sound = {
if(random() < 0.2) {
sound(self, CHAN_VOICE, "hknight/idle.wav", 1, ATTN_NORM);

View File

@ -1,4 +1,4 @@
// knight.qc: Knight
// m_knight.qc: Knight
$cd id1 / models / knight
$origin 0 0 24
@ -221,6 +221,19 @@ void() knight_die = {
}
};
void() knight_attack = {
float len;
// decide if now is a good swing time
len = vec_len(self.enemy.origin + self.enemy.view_ofs - (self.origin + self.view_ofs));
if(len < 80) {
knight_atk1();
} else {
knight_runatk1();
}
};
/*QUAKED monster_knight(1 0 0) (-16 -16 -24) (16 16 40) Ambush
*/
void() monster_knight = {

View File

@ -1,4 +1,4 @@
// ogre.qc: Ogre
// m_ogre.qc: Ogre
$cd id1 / models / ogre_c
$origin 0 0 24
@ -57,7 +57,7 @@ float() ogre_check_attack = {
float chance;
if(enemy_range == RANGE_MELEE) {
if(can_damage(self.enemy, self)) {
if(ent_can_damage(self.enemy, self)) {
self.attack_state = AS_MELEE;
return TRUE;
}
@ -198,7 +198,7 @@ void(float side) chainsaw = {
if(!self.enemy) {
return;
}
if(!can_damage(self.enemy, self)) {
if(!ent_can_damage(self.enemy, self)) {
return;
}
@ -295,9 +295,10 @@ void() ogre_swing12 = [ $swing12, ogre_swing13 ] {ai_charge(3);};
void() ogre_swing13 = [ $swing13, ogre_swing14 ] {ai_charge(8);};
void() ogre_swing14 = [ $swing14, ogre_run1 ] {ai_charge(9);};
void() ogre_smash1 = [ $smash1, ogre_smash2 ] {ai_charge(6);
sound(self, CHAN_WEAPON, "ogre/ogsawatk.wav", 1, ATTN_NORM);
};
void() ogre_smash1 = [ $smash1, ogre_smash2 ] {
ai_charge(6);
sound(self, CHAN_WEAPON, "ogre/ogsawatk.wav", 1, ATTN_NORM);
};
void() ogre_smash2 = [ $smash2, ogre_smash3 ] {ai_charge(0);};
void() ogre_smash3 = [ $smash3, ogre_smash4 ] {ai_charge(0);};
void() ogre_smash4 = [ $smash4, ogre_smash5 ] {ai_charge(1);};
@ -307,10 +308,11 @@ void() ogre_smash7 = [ $smash7, ogre_smash8 ] {ai_charge(4); chainsaw(0);};
void() ogre_smash8 = [ $smash8, ogre_smash9 ] {ai_charge(10); chainsaw(0);};
void() ogre_smash9 = [ $smash9, ogre_smash10 ] {ai_charge(13); chainsaw(0);};
void() ogre_smash10 = [ $smash10, ogre_smash11 ] {chainsaw(1);};
void() ogre_smash11 = [ $smash11, ogre_smash12 ] {ai_charge(2);
chainsaw(0);
self.nextthink = self.nextthink + random() * 0.2;
}; // slight variation
void() ogre_smash11 = [ $smash11, ogre_smash12 ] {
ai_charge(2);
chainsaw(0);
self.nextthink = time + 0.1 + random() * 0.2;
}; // slight variation
void() ogre_smash12 = [ $smash12, ogre_smash13 ] {ai_charge(0);};
void() ogre_smash13 = [ $smash13, ogre_smash14 ] {ai_charge(4);};
void() ogre_smash14 = [ $smash14, ogre_run1 ] {ai_charge(12);};

View File

@ -1,4 +1,4 @@
// oldone.qc: Shub-Niggurath
// m_oldone.qc: Shub-Niggurath
$cd id1 / models / old_one
$origin 0 0 24
@ -16,7 +16,7 @@ $frame shake1 shake2 shake3 shake4 shake5 shake6 shake7 shake8
$frame shake9 shake10 shake11 shake12 shake13 shake14
$frame shake15 shake16 shake17 shake18 shake19 shake20
//void() old_stand =[ $old1, old_stand ] {};
void() finale_1, finale_2, finale_3, finale_4;
void() old_idle1 = [ $old1, old_idle2 ] {};
void() old_idle2 = [ $old2, old_idle3 ] {};
@ -79,12 +79,13 @@ void() old_thrash11 = [ $shake11, old_thrash12 ] {light_style(0, "g");};
void() old_thrash12 = [ $shake12, old_thrash13 ] {light_style(0, "i");};
void() old_thrash13 = [ $shake13, old_thrash14 ] {light_style(0, "k");};
void() old_thrash14 = [ $shake14, old_thrash15 ] {light_style(0, "m");};
void() old_thrash15 = [ $shake15, old_thrash16 ] {light_style(0, "m");
self.cnt = self.cnt + 1;
if(self.cnt != 3) {
self.think = old_thrash1;
}
};
void() old_thrash15 = [ $shake15, old_thrash16 ] {
light_style(0, "m");
self.cnt = self.cnt + 1;
if(self.cnt != 3) {
self.think = old_thrash1;
}
};
void() old_thrash16 = [ $shake16, old_thrash17 ] {light_style(0, "g");};
void() old_thrash17 = [ $shake17, old_thrash18 ] {light_style(0, "c");};
void() old_thrash18 = [ $shake18, old_thrash19 ] {light_style(0, "b");};
@ -97,6 +98,9 @@ void() finale_1 = {
entity pos, pl;
entity timer;
killed_monsters++;
write_byte(MSG_ALL, SVC_KILLEDMONSTER);
intermission_exittime = time + 10000000; // never allow exit
intermission_running = 1;

View File

@ -1,4 +1,4 @@
// shalrath.qc: Vore
// m_shalrath.qc: Vore
$cd id1 / models / shalrath
$origin 0 0 24
@ -16,6 +16,8 @@ $frame death1 death2 death3 death4 death5 death6 death7
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10
$frame walk11 walk12
void() shalrath_home, shalrath_missile, shalrath_missile_touch;
void() shal_stand = [ $walk1, shal_stand ] {ai_stand();};
void() shal_walk1 = [ $walk2, shal_walk2 ] {

View File

@ -1,4 +1,4 @@
// shambler.qc: Shambler
// m_shambler.qc: Shambler
$cd id1 / models / shams
$origin 0 0 24
@ -30,6 +30,7 @@ $frame pain1 pain2 pain3 pain4 pain5 pain6
$frame death1 death2 death3 death4 death5 death6
$frame death7 death8 death9 death10 death11
void() sham_smash1, sham_swingl1, sham_swingr1;
/*
===========
sham_check_attack
@ -45,7 +46,7 @@ float() sham_check_attack = {
float enemy_yaw;
if(enemy_range == RANGE_MELEE) {
if(can_damage(self.enemy, self)) {
if(ent_can_damage(self.enemy, self)) {
self.attack_state = AS_MELEE;
return TRUE;
}
@ -161,7 +162,7 @@ void() sham_smash10 = [ $smash10, sham_smash11 ] {
if(vec_len(delta) > 100) {
return;
}
if(!can_damage(self.enemy, self)) {
if(!ent_can_damage(self.enemy, self)) {
return;
}
@ -278,24 +279,27 @@ void() sham_cast_lightning = {
lightning_damage(org, trace_endpos, self, 10);
};
void() sham_magic1 = [ $magic1, sham_magic2 ] {ai_face();
sound(self, CHAN_WEAPON, "shambler/sattck1.wav", 1, ATTN_NORM);
};
void() sham_magic1 = [ $magic1, sham_magic2 ] {
ai_face();
sound(self, CHAN_WEAPON, "shambler/sattck1.wav", 1, ATTN_NORM);
};
void() sham_magic2 = [ $magic2, sham_magic3 ] {ai_face();};
void() sham_magic3 = [ $magic3, sham_magic4 ] {ai_face();
self.nextthink = self.nextthink + 0.2;
entity o;
void() sham_magic3 = [ $magic3, sham_magic4 ] {
entity o;
self.effects = self.effects | EF_MUZZLEFLASH;
ai_face();
self.owner = spawn();
o = self.owner;
set_model(o, "progs/s_light.mdl");
set_origin(o, self.origin);
o.angles = self.angles;
o.nextthink = time + 0.7;
o.think = sub_remove;
};
ai_face();
self.nextthink = time + 0.2;
self.effects = self.effects | EF_MUZZLEFLASH;
ai_face();
self.owner = spawn();
o = self.owner;
set_model(o, "progs/s_light.mdl");
set_origin(o, self.origin);
o.angles = self.angles;
o.nextthink = time + 0.7;
o.think = sub_remove;
};
void() sham_magic4 = [ $magic4, sham_magic5 ] {
self.effects = self.effects | EF_MUZZLEFLASH;
self.owner.frame = 1;

View File

@ -1,4 +1,4 @@
// tarbaby.qc: Spawn
// m_tarbaby.qc: Spawn
$cd id1 / models / tarbaby
$origin 0 0 24
@ -20,6 +20,8 @@ $frame fly1 fly2 fly3 fly4
$frame exp
void() tbaby_jump1, tbaby_jump5;
void() tbaby_stand1 = [ $walk1, tbaby_stand1 ] {ai_stand();};
void() tbaby_hang1 = [ $walk1, tbaby_hang1 ] {ai_stand();};

View File

@ -1,4 +1,4 @@
// wizard.qc: Scrag
// m_wizard.qc: Scrag
$cd id1 / models / a_wizard
$origin 0 0 24
@ -18,6 +18,8 @@ $frame pain1 pain2 pain3 pain4
$frame death1 death2 death3 death4 death5 death6 death7 death8
void() wiz_run1, wiz_side1;
/*
==============================================================================

View File

@ -1,4 +1,4 @@
// zombie.qc: Zombie
// m_zombie.qc: Zombie
$cd id1 / models / zombie
@ -345,7 +345,7 @@ void() zombie_paine10 = [ $paine10, zombie_paine11 ] {
sound(self, CHAN_BODY, "zombie/z_fall.wav", 1, ATTN_NORM);
self.solid = SOLID_NOT;
};
void() zombie_paine11 = [ $paine11, zombie_paine12 ] {self.nextthink = self.nextthink + 5; self.health = 60;};
void() zombie_paine11 = [ $paine11, zombie_paine12 ] {self.nextthink = time + 5; self.health = 60;};
void() zombie_paine12 = [ $paine12, zombie_paine13 ] {
// see if ok to stand up
self.health = 60;
@ -424,7 +424,8 @@ void(entity attacker, float take) zombie_pain = {
}
if(self.inpain) {
// if hit again in next gre seconds while not in pain frames, definately drop
// if hit again in next three seconds while not in pain frames,
// definitely drop
self.pain_finished = time + 3;
return; // currently going through an animation, don't change
}

View File

@ -1,4 +1,44 @@
// client.qc: player-adjacent functions
// p_client.qc: player-adjacent functions
void() impulse_commands;
/*
=============================================================================
QUAKED FUNCTIONS
=============================================================================
*/
/*QUAKED info_player_start(1 0 0) (-16 -16 -24) (16 16 24)
The normal starting point for a level.
*/
void() info_player_start = {
};
/*QUAKED info_player_start2(1 0 0) (-16 -16 -24) (16 16 24)
Only used on start map for the return point from an episode.
*/
void() info_player_start2 = {
};
/*
saved out by quaked in region mode
*/
void() testplayerstart = {
};
/*QUAKED info_player_deathmatch(1 0 1) (-16 -16 -24) (16 16 24)
potential spawning position for deathmatch games
*/
void() info_player_deathmatch = {
};
/*QUAKED info_player_coop(1 0 1) (-16 -16 -24) (16 16 24)
potential spawning position for coop games
*/
void() info_player_coop = {
};
string(float pro) pronoun_subject = {
switch(pro) {
@ -85,10 +125,8 @@ void() SetNewParms = {
void() decode_level_parms = {
float ofs, ofs2, pro;
if(serverflags) {
if(world.model == "maps/start.bsp") {
SetNewParms(); // take away all stuff on starting new episode
}
if(!deathmatch && world.model == "maps/start.bsp") {
SetNewParms(); // take away all stuff on starting new episode
}
self.items = parm1;
@ -257,7 +295,7 @@ void() intermission_exit = {
}
intermission_exittime = time + 1;
intermission_running = intermission_running + 1;
intermission_running++;
//
// run some text if at the end of an episode
@ -578,7 +616,7 @@ entity() select_spawn_point = {
thing = find_radius(spot.origin, 32);
while(thing) {
if(thing.classname == "player") {
pcount = pcount + 1;
pcount++;
}
thing = thing.chain;
}
@ -674,9 +712,10 @@ void() PutClientInServer = {
// pausetime is set by teleporters to keep the player from moving for a bit
self.pausetime = 0;
self.origin = spot.origin + '0 0 1';
self.angles = spot.angles;
self.fixangle = TRUE; // turn this way immediately
self.origin = spot.origin + '0 0 1';
self.oldorigin = self.origin;
self.angles = spot.angles;
self.fixangle = TRUE; // turn this way immediately
// oh, this is a hack!
set_model(self, "progs/eyes.mdl");
@ -688,6 +727,7 @@ void() PutClientInServer = {
set_size(self, '-16 -16 -24', '16 16 32');
self.view_ofs = '0 0 22';
self.velocity = VEC_ORIGIN;
player_stand1();
@ -699,44 +739,6 @@ void() PutClientInServer = {
spawn_tdeath(self.origin, self);
};
/*
=============================================================================
QUAKED FUNCTIONS
=============================================================================
*/
/*QUAKED info_player_start(1 0 0) (-16 -16 -24) (16 16 24)
The normal starting point for a level.
*/
void() info_player_start = {
};
/*QUAKED info_player_start2(1 0 0) (-16 -16 -24) (16 16 24)
Only used on start map for the return point from an episode.
*/
void() info_player_start2 = {
};
/*
saved out by quaked in region mode
*/
void() testplayerstart = {
};
/*QUAKED info_player_deathmatch(1 0 1) (-16 -16 -24) (16 16 24)
potential spawning position for deathmatch games
*/
void() info_player_deathmatch = {
};
/*QUAKED info_player_coop(1 0 1) (-16 -16 -24) (16 16 24)
potential spawning position for coop games
*/
void() info_player_coop = {
};
/*
===============================================================================
@ -1180,7 +1182,7 @@ Called every frame after physics are run
================
*/
void() PlayerPostThink = {
if(time >= self.attack_finished) {
if(time >= self.attack_finished && self.impulse) {
impulse_commands();
}
@ -1345,7 +1347,7 @@ void() impulse_commands = {
};
float(entity targ, entity attacker) obit_teledeath = {
attacker.owner.frags = attacker.owner.frags + 1;
attacker.owner.frags++;
print_all(" was telefragged by ", attacker.owner.netname, "\n");
return TRUE;
};
@ -1356,6 +1358,15 @@ float(entity targ, entity attacker) obit_teledeath2 = {
return TRUE;
};
float(entity targ, entity attacker) obit_teledeath3 = {
targ.frags--;
attacker.owner.frags++;
print_all(" was telefragged by ",
attacker.owner.netname,
"'s satanic powers\n");
return TRUE;
};
float(entity targ, entity attacker) obit_suicide = {
targ.frags--;
@ -1402,7 +1413,7 @@ float(entity targ, entity attacker) obit_teamkill = {
float(entity targ, entity attacker) obit_pkill = {
string deathstring, deathstring2;
attacker.frags = attacker.frags + 1;
attacker.frags++;
switch(attacker.weapon) {
case IT_AXE:
@ -1682,6 +1693,9 @@ void(entity targ, entity attacker) client_obituary = {
case "teledeath2":
did_message = obit_teledeath2(targ, attacker);
break;
case "teledeath3":
did_message = obit_teledeath3(targ, attacker);
break;
case "player":
if(targ == attacker) {
did_message = obit_suicide(targ, attacker);

View File

@ -1,4 +1,4 @@
// player.qc: the player entity
// p_player.qc: the player entity
$cd id1 / models / player_4
$origin 0 - 6 24
@ -68,6 +68,11 @@ $frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6
$frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
void() player_die_ax1, player_diea1, player_dieb1, player_diec1, player_died1,
player_diee1;
void(float num_bubbles) death_bubbles;
/*
==============================================================================
PLAYER
@ -249,7 +254,9 @@ void() player_pain_sound = {
// slime pain sounds
if(self.watertype == CONTENT_SLIME) {
// FIX ME put in some steam here
if(self.waterlevel == 3) {
death_bubbles(1);
}
if(random() > 0.5) {
sound(self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM);
} else {
@ -335,7 +342,8 @@ void(entity attacker, float damage) player_pain = {
void() player_death_bubbles_spawn = {
entity bubble;
if(self.owner.waterlevel != 3) {
if(self.owner.waterlevel != 3 && self.owner.health > 0) {
remove(self);
return;
}
bubble = spawn();
@ -350,7 +358,7 @@ void() player_death_bubbles_spawn = {
bubble.frame = 0;
bubble.cnt = 0;
set_size(bubble, '-8 -8 -8', '8 8 8');
self.nextthink = time + 0.1;
self.nextthink = time + 0.01;
self.think = player_death_bubbles_spawn;
self.air_finished = self.air_finished + 1;
if(self.air_finished >= self.bubble_count) {
@ -365,12 +373,11 @@ void(float num_bubbles) death_bubbles = {
set_origin(bubble_spawner, self.origin);
bubble_spawner.movetype = MOVETYPE_NONE;
bubble_spawner.solid = SOLID_NOT;
bubble_spawner.nextthink = time + 0.1;
bubble_spawner.nextthink = time + 0.01;
bubble_spawner.think = player_death_bubbles_spawn;
bubble_spawner.air_finished = 0;
bubble_spawner.owner = self;
bubble_spawner.bubble_count = num_bubbles;
return;
};
void() player_death_sound = {
@ -493,11 +500,12 @@ void() player_gib = {
void() player_die = {
float i;
self.items = self.items - (self.items & IT_INVISIBILITY);
self.items &= ~(IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD);
self.invisible_finished = 0; // don't die as eyes
self.invincible_finished = 0;
self.super_damage_finished = 0;
self.radsuit_finished = 0;
self.effects = 0;
self.modelindex = modelindex_player; // don't use eyes
if(deathmatch || coop) {

View File

@ -1,4 +1,4 @@
// weapons.qc: weapon functions
// p_weapons.qc: weapon functions
// called by worldspawn
void() wep_precache = {
@ -533,6 +533,43 @@ void() wep_fire_grenade = {
//=============================================================================
void() spike_touch = {
float rand;
if(other == self.owner) {
return;
}
if(other.solid == SOLID_TRIGGER) {
return; // trigger field, do nothing
}
if(point_contents(self.origin) == CONTENT_SKY) {
remove(self);
return;
}
// hit something that bleeds
if(other.takedamage) {
spawn_touchblood(9);
ent_damage(other, self, self.owner, 9);
} else {
write_byte(MSG_BROADCAST, SVC_TEMPENTITY);
if(self.classname == "wizspike") {
write_byte(MSG_BROADCAST, TE_WIZSPIKE);
} else if(self.classname == "knightspike") {
write_byte(MSG_BROADCAST, TE_KNIGHTSPIKE);
} else {
write_byte(MSG_BROADCAST, TE_SPIKE);
}
write_coord(MSG_BROADCAST, self.origin_x);
write_coord(MSG_BROADCAST, self.origin_y);
write_coord(MSG_BROADCAST, self.origin_z);
}
remove(self);
};
/*
===============
launch_spike