implement various fixes and refactorings

This commit is contained in:
alison wright 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 progs.dat
source/defs.qc source/c_defs.qc
source/common.qc source/c_common.qc
source/c_combat.qc
source/fight.qc
source/subs.qc
source/ai.qc source/ai.qc
source/buttons.qc source/ai_fight.qc
source/client.qc source/ai_monsters.qc
source/combat.qc source/ai_subs.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/boss.qc source/p_client.qc
source/demon.qc source/p_player.qc
source/dog.qc source/p_weapons.qc
source/knight.qc
source/ogre.qc
source/shambler.qc
source/soldier.qc
source/wizard.qc
source/zombie.qc
source/enforcer.qc source/w_buttons.qc
source/fish.qc source/w_doors.qc
source/hknight.qc source/w_items.qc
source/oldone.qc source/w_misc.qc
source/shalrath.qc source/w_plats.qc
source/tarbaby.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 t_movetarget
@ -83,7 +65,6 @@ void() t_movetarget = {
sound(self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE); // play chainsaw drag sound 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.goalentity = self.movetarget = find(world, targetname, other.target);
self.ideal_yaw = vec_yaw(self.goalentity.origin - self.origin); self.ideal_yaw = vec_yaw(self.goalentity.origin - self.origin);
if(!self.movetarget) { 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 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) { if(vec_len(delta) > 60) {
return; return;
} }
if(!can_damage(self.enemy, self)) { if(!ent_can_damage(self.enemy, self)) {
return; return;
} }
ldmg = (random() + random() + random()) * 3; 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 */ /* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */
@ -12,6 +12,11 @@
// <code> // <code>
// }; // };
float() enemy_is_high = {
return !self.enemy ||
fabs(self.enemy.origin_z - self.origin_z) >= AI_MONSTER_HIGH;
};
/* /*
================ ================
monster_use monster_use
@ -113,13 +118,13 @@ void() walkmonster_start_go = {
} }
// spread think times so they don't all happen at same time // 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 = { void() walkmonster_start = {
// delay drop to floor to make sure all doors have been spawned // delay drop to floor to make sure all doors have been spawned
// spread think times so they don't all happen at same time // 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; self.think = walkmonster_start_go;
total_monsters = total_monsters + 1; total_monsters = total_monsters + 1;
}; };
@ -158,11 +163,13 @@ void() flymonster_start_go = {
self.pausetime = 99999999; self.pausetime = 99999999;
self.th_stand(); self.th_stand();
} }
self.nextthink = time + 0.1 + random() * 0.5;
}; };
void() flymonster_start = { void() flymonster_start = {
// spread think times so they don't all happen at same time // 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; self.think = flymonster_start_go;
total_monsters = total_monsters + 1; total_monsters = total_monsters + 1;
}; };
@ -174,7 +181,6 @@ void() swimmonster_start_go = {
} }
self.takedamage = DAMAGE_AIM; self.takedamage = DAMAGE_AIM;
total_monsters = total_monsters + 1;
self.ideal_yaw = self.angles * '0 1 0'; self.ideal_yaw = self.angles * '0 1 0';
if(!self.yaw_speed) { if(!self.yaw_speed) {
@ -200,12 +206,13 @@ void() swimmonster_start_go = {
} }
// spread think times so they don't all happen at same time // 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 = { void() swimmonster_start = {
// spread think times so they don't all happen at same time // 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; self.think = swimmonster_start_go;
total_monsters = total_monsters + 1; 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() sub_null = {};
void(entity attacker, float damage) sub_pain_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 = { float(entity targ, entity attacker) is_same_team = {
return targ != attacker && 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 Returns true if the inflictor can directly damage the target. Used for
explosions and melee attacks. 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 // bmodels need special checking because their origin is 0,0,0
if(targ.movetype == MOVETYPE_PUSH) { if(targ.movetype == MOVETYPE_PUSH) {
trace_line(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self); 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; float points;
entity head; entity head;
vector org; vector org;
float attacker_damaged;
float attacker_points;
head = find_radius(inflictor.origin, damage + 40); head = find_radius(inflictor.origin, damage + 40);
while(head) { while(head) {
if(head != ignore) { if(head != ignore && head.takedamage) {
if(head.takedamage) {
org = head.origin + (head.mins + head.maxs) * 0.5; org = head.origin + (head.mins + head.maxs) * 0.5;
points = 0.5 * vec_len(inflictor.origin - org); points = 0.5 * vec_len(inflictor.origin - org);
if(points < 0) { if(points < 0) {
points = 0; points = 0;
} }
points = damage - points; points = damage - points;
if(head == attacker) { if(points > 0 && ent_can_damage(head, inflictor)) {
points = points * 0.5; if(head != attacker) {
}
if(points > 0) {
if(can_damage(head, inflictor)) {
// shambler takes half damage from all explosions // shambler takes half damage from all explosions
if(head.classname == "monster_shambler") { if(head.classname == "monster_shambler") {
ent_damage(head, inflictor, attacker, points * 0.5); ent_damage(head, inflictor, attacker, points * 0.5);
} else { } else {
ent_damage(head, inflictor, attacker, points); ent_damage(head, inflictor, attacker, points);
} }
} } else {
attacker_damaged = TRUE;
attacker_points = points * 0.5;
} }
} }
} }
head = head.chain; 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; points = points * 0.5;
} }
if(points > 0) { if(points > 0) {
if(can_damage(head, attacker)) { if(ent_can_damage(head, attacker)) {
if(head.classname == "monster_shambler") { if(head.classname == "monster_shambler") {
ent_damage(head, attacker, attacker, points * 0.5); ent_damage(head, attacker, attacker, points * 0.5);
} else { } else {

View File

@ -1,4 +1,4 @@
// common.qc: common functions // c_common.qc: common functions
const float PO2_LUT[25] = { const float PO2_LUT[25] = {
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 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; spot2 = targ.origin + targ.view_ofs;
r = vec_len(spot1 - spot2); r = vec_len(spot1 - spot2);
if(r < 120) { if(r < AI_RANGE_MELEE) {
return RANGE_MELEE; return RANGE_MELEE;
} } else if(r < AI_RANGE_NEAR) {
if(r < 500) {
return RANGE_NEAR; return RANGE_NEAR;
} } else if(r < AI_RANGE_MID) {
if(r < 1000) {
return 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() // 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 ------------------------------------------------------------| // system globals ------------------------------------------------------------|
#pragma noref 1 #pragma noref 1
@ -417,13 +417,41 @@ enum {
// protocol bytes // protocol bytes
enum { enum {
SVC_TEMPENTITY = 23, SVC_BAD,
SVC_KILLEDMONSTER = 27, SVC_NOP,
SVC_FOUNDSECRET = 28, SVC_DISCONNECT,
SVC_INTERMISSION = 30, SVC_UPDATESTAT,
SVC_FINALE = 31, SVC_VERSION,
SVC_CDTRACK = 32, SVC_SETVIEW,
SVC_SELLSCREEN = 33, 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 { enum {
@ -573,6 +601,13 @@ enum {
CHANGELEVEL_NO_INTERMISSION = 1, 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 // super co-op additions
enum { enum {
PRO_NONE, PRO_NONE,
@ -791,171 +826,98 @@ float ext_strings;
.float lives; .float lives;
.float spectating; .float spectating;
.float hurt_together_time;
.float hurt_nextthink;
// functions -----------------------------------------------------------------| // 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() sub_calc_angle_move_done;
void(void() thinkst) sub_check_refire; void() sub_calc_move_done;
void() sub_null; void() sub_null;
void(entity attacker, float damage) sub_pain_null;
void() sub_use_targets;
void() sub_remove; 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 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() ent_missile_touch;
void(entity bomb, entity attacker, float rad, entity ignore) ent_radius_damage; void(entity bomb, entity attacker, float rad, entity ignore) ent_radius_damage;
void(entity targ, entity inflictor, entity attacker, float damage) ent_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; 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_set_current_ammo;
void() wep_weapon_frame; void() wep_weapon_frame;
void(float ox) wep_fire_nail;
void(float wep) wep_change_weapon;
string() key_1_name; string() key_1_name, key_2_name;
string() 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(entity ent) copy_to_body_queue;
void() init_body_queue;
void() super_damage_sound; void() super_damage_sound;
void() ai_face;
void() armor_touch; void() armor_touch;
void() bubble_bob; void() bubble_bob;
void() bubble_remove;
void() button_return;
void() button_wait;
void() door_go_down; 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() monster_death_use;
void() movetarget_f;
void() powerup_touch;
void() set_suicide_frame; void() set_suicide_frame;
void(vector org, vector dir) launch_spike; void(vector org, vector dir) launch_spike;
void() spike_touch;
void() superspike_touch; void() superspike_touch;
void() swimmonster_start;
void() t_movetarget;
void() train_next; void() swimmonster_start;
void(entity targ, entity attacker) client_obituary; 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 vec) launch_laser;
void(vector org, vector vel, float damage) spawn_blood; void(vector org, vector vel, float damage) spawn_blood;
void() become_explosion; void() become_explosion;
void() hknight_char_a1; float() army_check_attack;
void() hknight_run1; float() demon_check_attack;
float() dog_check_attack;
void() ogre_smash1;
void() ogre_swing1;
float() ogre_check_attack; float() ogre_check_attack;
float() sham_check_attack;
float() wiz_check_attack;
void() plat_center_touch; void() knight_attack;
void() plat_crush;
void() plat_go_down;
void() plat_go_up;
void() plat_outside_touch;
void() plat_trigger_use;
void() knight_atk1;
void() knight_bow1;
void() knight_bow6;
void() knight_runatk1;
void() knight_walk1;
void() player_die;
void() player_axe1; void() player_axe1;
void() player_axeb1; void() player_axeb1;
void() player_axec1; void() player_axec1;
void() player_axed1; void() player_axed1;
void() player_die_ax1; void() player_die;
void() player_diea1;
void() player_dieb1;
void() player_diec1;
void() player_died1;
void() player_diee1;
void() player_light1; void() player_light1;
void() player_nail1; void() player_nail1;
void(entity attacker, float damage) player_pain;
void() player_rocket1; void() player_rocket1;
void() player_run; void() player_run;
void() player_run;
void() player_shot1; void() player_shot1;
void() player_stand1; void() player_stand1;
void(entity attacker, float damage) player_pain;
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(vector org) spawn_tfog; void(vector org) spawn_tfog;
void(vector org, entity death_owner) spawn_tdeath; 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 // EOF

View File

@ -1,4 +1,4 @@
// soldier.qc: Grunt // m_army.qc: Grunt
$cd id1 / models / soldier3 $cd id1 / models / soldier3
$origin 0 - 6 24 $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_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 $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 $cd id1 / models / boss1
$origin 0 0 - 15 $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 shockc1 shockc2 shockc3 shockc4 shockc5 shockc6 shockc7 shockc8
$frame shockc9 shockc10 $frame shockc9 shockc10
void(vector p) boss_missile;
void() boss_face = { void() boss_face = {
// go for another player if multi player // go for another player if multi player
if(enemy_is_gone(self.enemy) || random() < 0.02) { 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] { void() boss_death10 = [$death9, boss_death10] {
killed_monsters = killed_monsters + 1; killed_monsters = killed_monsters + 1;
write_byte(MSG_ALL, SVC_KILLEDMONSTER); // FIXME: reliable broadcast write_byte(MSG_ALL, SVC_KILLEDMONSTER);
sub_use_targets(); sub_use_targets();
remove(self); remove(self);
}; };

View File

@ -1,4 +1,4 @@
// demon.qc: Fiend // m_demon.qc: Fiend
$cd id1 / models / demon3 $cd id1 / models / demon3
$scale 0.8 $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 attacka1 attacka2 attacka3 attacka4 attacka5 attacka6 attacka7 attacka8
$frame attacka9 attacka10 attacka11 attacka12 attacka13 attacka14 attacka15 $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();}; 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 = { float() demon_check_melee = {
if(enemy_range == RANGE_MELEE) { if(enemy_range == RANGE_MELEE && !enemy_is_high()) {
// FIXME: check canreach
self.attack_state = AS_MELEE; self.attack_state = AS_MELEE;
return TRUE; return TRUE;
} } else {
return FALSE; return FALSE;
}
}; };
/* /*
@ -237,13 +240,10 @@ float() demon_check_jump = {
vector dist; vector dist;
float d; float d;
if(self.origin_z + self.mins_z > self.enemy.origin_z + self.enemy.mins_z if(self.origin_z + self.mins_z >
+ 0.75 * self.enemy.size_z) { self.enemy.origin_z + self.enemy.mins_z + 0.75 * self.enemy.size_z ||
return FALSE; 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.maxs_z < self.enemy.origin_z + self.enemy.mins_z
+ 0.25 * self.enemy.size_z) {
return FALSE; return FALSE;
} }
@ -252,17 +252,7 @@ float() demon_check_jump = {
d = vec_len(dist); d = vec_len(dist);
if(d < 100) { return !(d < 100 || (d > 200 && random() < 0.9));
return FALSE;
}
if(d > 200) {
if(random() < 0.9) {
return FALSE;
}
}
return TRUE;
}; };
float() demon_check_attack = { float() demon_check_attack = {
@ -297,7 +287,7 @@ void(float side) demon_melee = {
if(vec_len(delta) > 100) { if(vec_len(delta) > 100) {
return; return;
} }
if(!can_damage(self.enemy, self)) { if(!ent_can_damage(self.enemy, self)) {
return; return;
} }

View File

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

View File

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

View File

@ -1,4 +1,4 @@
// fish.qc: Rotfish // m_fish.qc: Rotfish
$cd id1 / models / fish $cd id1 / models / fish
$origin 0 0 24 $origin 0 0 24
@ -114,7 +114,7 @@ void() f_death1 = [ $death1, f_death2 ] {
sound(self, CHAN_VOICE, "fish/death.wav", 1, ATTN_NORM); sound(self, CHAN_VOICE, "fish/death.wav", 1, ATTN_NORM);
}; };
void() f_death2 = [ $death2, f_death3 ] {}; 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_death4 = [ $death4, f_death5 ] {};
void() f_death5 = [ $death5, f_death6 ] {}; void() f_death5 = [ $death5, f_death6 ] {};
void() f_death6 = [ $death6, f_death7 ] {}; void() f_death6 = [ $death6, f_death7 ] {};
@ -132,7 +132,7 @@ void() f_death17 = [ $death17, f_death18 ] {};
void() f_death18 = [ $death18, f_death19 ] {}; void() f_death18 = [ $death18, f_death19 ] {};
void() f_death19 = [ $death19, f_death20 ] {}; void() f_death19 = [ $death19, f_death20 ] {};
void() f_death20 = [ $death20, f_death21 ] {}; 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_pain1 = [ $pain1, f_pain2 ] {};
void() f_pain2 = [ $pain2, f_pain3 ] {ai_pain(6);}; 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() f_pain9 = [ $pain9, f_run1 ] {ai_pain(6);};
void(entity attacker, float damage) fish_pain = { void(entity attacker, float damage) fish_pain = {
// fish allways do pain frames // fish allways do pain frames
f_pain1(); 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 /*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_stand = f_stand1;
self.th_walk = f_walk1; self.th_walk = f_walk1;
self.th_run = f_run1; self.th_run = f_run1;
self.th_die = f_death1; self.th_die = f_die;
self.th_pain = fish_pain; self.th_pain = fish_pain;
self.th_melee = f_attack1; self.th_melee = f_attack1;

View File

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

View File

@ -1,4 +1,4 @@
// ogre.qc: Ogre // m_ogre.qc: Ogre
$cd id1 / models / ogre_c $cd id1 / models / ogre_c
$origin 0 0 24 $origin 0 0 24
@ -57,7 +57,7 @@ float() ogre_check_attack = {
float chance; float chance;
if(enemy_range == RANGE_MELEE) { if(enemy_range == RANGE_MELEE) {
if(can_damage(self.enemy, self)) { if(ent_can_damage(self.enemy, self)) {
self.attack_state = AS_MELEE; self.attack_state = AS_MELEE;
return TRUE; return TRUE;
} }
@ -198,7 +198,7 @@ void(float side) chainsaw = {
if(!self.enemy) { if(!self.enemy) {
return; return;
} }
if(!can_damage(self.enemy, self)) { if(!ent_can_damage(self.enemy, self)) {
return; 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_swing13 = [ $swing13, ogre_swing14 ] {ai_charge(8);};
void() ogre_swing14 = [ $swing14, ogre_run1 ] {ai_charge(9);}; void() ogre_swing14 = [ $swing14, ogre_run1 ] {ai_charge(9);};
void() ogre_smash1 = [ $smash1, ogre_smash2 ] {ai_charge(6); void() ogre_smash1 = [ $smash1, ogre_smash2 ] {
ai_charge(6);
sound(self, CHAN_WEAPON, "ogre/ogsawatk.wav", 1, ATTN_NORM); sound(self, CHAN_WEAPON, "ogre/ogsawatk.wav", 1, ATTN_NORM);
}; };
void() ogre_smash2 = [ $smash2, ogre_smash3 ] {ai_charge(0);}; void() ogre_smash2 = [ $smash2, ogre_smash3 ] {ai_charge(0);};
void() ogre_smash3 = [ $smash3, ogre_smash4 ] {ai_charge(0);}; void() ogre_smash3 = [ $smash3, ogre_smash4 ] {ai_charge(0);};
void() ogre_smash4 = [ $smash4, ogre_smash5 ] {ai_charge(1);}; 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_smash8 = [ $smash8, ogre_smash9 ] {ai_charge(10); chainsaw(0);};
void() ogre_smash9 = [ $smash9, ogre_smash10 ] {ai_charge(13); chainsaw(0);}; void() ogre_smash9 = [ $smash9, ogre_smash10 ] {ai_charge(13); chainsaw(0);};
void() ogre_smash10 = [ $smash10, ogre_smash11 ] {chainsaw(1);}; void() ogre_smash10 = [ $smash10, ogre_smash11 ] {chainsaw(1);};
void() ogre_smash11 = [ $smash11, ogre_smash12 ] {ai_charge(2); void() ogre_smash11 = [ $smash11, ogre_smash12 ] {
ai_charge(2);
chainsaw(0); chainsaw(0);
self.nextthink = self.nextthink + random() * 0.2; self.nextthink = time + 0.1 + random() * 0.2;
}; // slight variation }; // slight variation
void() ogre_smash12 = [ $smash12, ogre_smash13 ] {ai_charge(0);}; void() ogre_smash12 = [ $smash12, ogre_smash13 ] {ai_charge(0);};
void() ogre_smash13 = [ $smash13, ogre_smash14 ] {ai_charge(4);}; void() ogre_smash13 = [ $smash13, ogre_smash14 ] {ai_charge(4);};
void() ogre_smash14 = [ $smash14, ogre_run1 ] {ai_charge(12);}; 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 $cd id1 / models / old_one
$origin 0 0 24 $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 shake9 shake10 shake11 shake12 shake13 shake14
$frame shake15 shake16 shake17 shake18 shake19 shake20 $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_idle1 = [ $old1, old_idle2 ] {};
void() old_idle2 = [ $old2, old_idle3 ] {}; 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_thrash12 = [ $shake12, old_thrash13 ] {light_style(0, "i");};
void() old_thrash13 = [ $shake13, old_thrash14 ] {light_style(0, "k");}; void() old_thrash13 = [ $shake13, old_thrash14 ] {light_style(0, "k");};
void() old_thrash14 = [ $shake14, old_thrash15 ] {light_style(0, "m");}; void() old_thrash14 = [ $shake14, old_thrash15 ] {light_style(0, "m");};
void() old_thrash15 = [ $shake15, old_thrash16 ] {light_style(0, "m"); void() old_thrash15 = [ $shake15, old_thrash16 ] {
light_style(0, "m");
self.cnt = self.cnt + 1; self.cnt = self.cnt + 1;
if(self.cnt != 3) { if(self.cnt != 3) {
self.think = old_thrash1; self.think = old_thrash1;
} }
}; };
void() old_thrash16 = [ $shake16, old_thrash17 ] {light_style(0, "g");}; void() old_thrash16 = [ $shake16, old_thrash17 ] {light_style(0, "g");};
void() old_thrash17 = [ $shake17, old_thrash18 ] {light_style(0, "c");}; void() old_thrash17 = [ $shake17, old_thrash18 ] {light_style(0, "c");};
void() old_thrash18 = [ $shake18, old_thrash19 ] {light_style(0, "b");}; void() old_thrash18 = [ $shake18, old_thrash19 ] {light_style(0, "b");};
@ -97,6 +98,9 @@ void() finale_1 = {
entity pos, pl; entity pos, pl;
entity timer; entity timer;
killed_monsters++;
write_byte(MSG_ALL, SVC_KILLEDMONSTER);
intermission_exittime = time + 10000000; // never allow exit intermission_exittime = time + 10000000; // never allow exit
intermission_running = 1; intermission_running = 1;

View File

@ -1,4 +1,4 @@
// shalrath.qc: Vore // m_shalrath.qc: Vore
$cd id1 / models / shalrath $cd id1 / models / shalrath
$origin 0 0 24 $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 walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10
$frame walk11 walk12 $frame walk11 walk12
void() shalrath_home, shalrath_missile, shalrath_missile_touch;
void() shal_stand = [ $walk1, shal_stand ] {ai_stand();}; void() shal_stand = [ $walk1, shal_stand ] {ai_stand();};
void() shal_walk1 = [ $walk2, shal_walk2 ] { void() shal_walk1 = [ $walk2, shal_walk2 ] {

View File

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

View File

@ -1,4 +1,4 @@
// tarbaby.qc: Spawn // m_tarbaby.qc: Spawn
$cd id1 / models / tarbaby $cd id1 / models / tarbaby
$origin 0 0 24 $origin 0 0 24
@ -20,6 +20,8 @@ $frame fly1 fly2 fly3 fly4
$frame exp $frame exp
void() tbaby_jump1, tbaby_jump5;
void() tbaby_stand1 = [ $walk1, tbaby_stand1 ] {ai_stand();}; void() tbaby_stand1 = [ $walk1, tbaby_stand1 ] {ai_stand();};
void() tbaby_hang1 = [ $walk1, tbaby_hang1 ] {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 $cd id1 / models / a_wizard
$origin 0 0 24 $origin 0 0 24
@ -18,6 +18,8 @@ $frame pain1 pain2 pain3 pain4
$frame death1 death2 death3 death4 death5 death6 death7 death8 $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 $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); sound(self, CHAN_BODY, "zombie/z_fall.wav", 1, ATTN_NORM);
self.solid = SOLID_NOT; 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 ] { void() zombie_paine12 = [ $paine12, zombie_paine13 ] {
// see if ok to stand up // see if ok to stand up
self.health = 60; self.health = 60;
@ -424,7 +424,8 @@ void(entity attacker, float take) zombie_pain = {
} }
if(self.inpain) { 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; self.pain_finished = time + 3;
return; // currently going through an animation, don't change 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 = { string(float pro) pronoun_subject = {
switch(pro) { switch(pro) {
@ -85,11 +125,9 @@ void() SetNewParms = {
void() decode_level_parms = { void() decode_level_parms = {
float ofs, ofs2, pro; float ofs, ofs2, pro;
if(serverflags) { if(!deathmatch && world.model == "maps/start.bsp") {
if(world.model == "maps/start.bsp") {
SetNewParms(); // take away all stuff on starting new episode SetNewParms(); // take away all stuff on starting new episode
} }
}
self.items = parm1; self.items = parm1;
self.health = parm2; self.health = parm2;
@ -257,7 +295,7 @@ void() intermission_exit = {
} }
intermission_exittime = time + 1; intermission_exittime = time + 1;
intermission_running = intermission_running + 1; intermission_running++;
// //
// run some text if at the end of an episode // run some text if at the end of an episode
@ -578,7 +616,7 @@ entity() select_spawn_point = {
thing = find_radius(spot.origin, 32); thing = find_radius(spot.origin, 32);
while(thing) { while(thing) {
if(thing.classname == "player") { if(thing.classname == "player") {
pcount = pcount + 1; pcount++;
} }
thing = thing.chain; thing = thing.chain;
} }
@ -675,6 +713,7 @@ void() PutClientInServer = {
self.pausetime = 0; self.pausetime = 0;
self.origin = spot.origin + '0 0 1'; self.origin = spot.origin + '0 0 1';
self.oldorigin = self.origin;
self.angles = spot.angles; self.angles = spot.angles;
self.fixangle = TRUE; // turn this way immediately self.fixangle = TRUE; // turn this way immediately
@ -688,6 +727,7 @@ void() PutClientInServer = {
set_size(self, '-16 -16 -24', '16 16 32'); set_size(self, '-16 -16 -24', '16 16 32');
self.view_ofs = '0 0 22'; self.view_ofs = '0 0 22';
self.velocity = VEC_ORIGIN;
player_stand1(); player_stand1();
@ -699,44 +739,6 @@ void() PutClientInServer = {
spawn_tdeath(self.origin, self); 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 = { void() PlayerPostThink = {
if(time >= self.attack_finished) { if(time >= self.attack_finished && self.impulse) {
impulse_commands(); impulse_commands();
} }
@ -1345,7 +1347,7 @@ void() impulse_commands = {
}; };
float(entity targ, entity attacker) obit_teledeath = { 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"); print_all(" was telefragged by ", attacker.owner.netname, "\n");
return TRUE; return TRUE;
}; };
@ -1356,6 +1358,15 @@ float(entity targ, entity attacker) obit_teledeath2 = {
return TRUE; 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 = { float(entity targ, entity attacker) obit_suicide = {
targ.frags--; targ.frags--;
@ -1402,7 +1413,7 @@ float(entity targ, entity attacker) obit_teamkill = {
float(entity targ, entity attacker) obit_pkill = { float(entity targ, entity attacker) obit_pkill = {
string deathstring, deathstring2; string deathstring, deathstring2;
attacker.frags = attacker.frags + 1; attacker.frags++;
switch(attacker.weapon) { switch(attacker.weapon) {
case IT_AXE: case IT_AXE:
@ -1682,6 +1693,9 @@ void(entity targ, entity attacker) client_obituary = {
case "teledeath2": case "teledeath2":
did_message = obit_teledeath2(targ, attacker); did_message = obit_teledeath2(targ, attacker);
break; break;
case "teledeath3":
did_message = obit_teledeath3(targ, attacker);
break;
case "player": case "player":
if(targ == attacker) { if(targ == attacker) {
did_message = obit_suicide(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 $cd id1 / models / player_4
$origin 0 - 6 24 $origin 0 - 6 24
@ -68,6 +68,11 @@ $frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6
$frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6 $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 PLAYER
@ -249,7 +254,9 @@ void() player_pain_sound = {
// slime pain sounds // slime pain sounds
if(self.watertype == CONTENT_SLIME) { if(self.watertype == CONTENT_SLIME) {
// FIX ME put in some steam here if(self.waterlevel == 3) {
death_bubbles(1);
}
if(random() > 0.5) { if(random() > 0.5) {
sound(self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM); sound(self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM);
} else { } else {
@ -335,7 +342,8 @@ void(entity attacker, float damage) player_pain = {
void() player_death_bubbles_spawn = { void() player_death_bubbles_spawn = {
entity bubble; entity bubble;
if(self.owner.waterlevel != 3) { if(self.owner.waterlevel != 3 && self.owner.health > 0) {
remove(self);
return; return;
} }
bubble = spawn(); bubble = spawn();
@ -350,7 +358,7 @@ void() player_death_bubbles_spawn = {
bubble.frame = 0; bubble.frame = 0;
bubble.cnt = 0; bubble.cnt = 0;
set_size(bubble, '-8 -8 -8', '8 8 8'); 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.think = player_death_bubbles_spawn;
self.air_finished = self.air_finished + 1; self.air_finished = self.air_finished + 1;
if(self.air_finished >= self.bubble_count) { if(self.air_finished >= self.bubble_count) {
@ -365,12 +373,11 @@ void(float num_bubbles) death_bubbles = {
set_origin(bubble_spawner, self.origin); set_origin(bubble_spawner, self.origin);
bubble_spawner.movetype = MOVETYPE_NONE; bubble_spawner.movetype = MOVETYPE_NONE;
bubble_spawner.solid = SOLID_NOT; 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.think = player_death_bubbles_spawn;
bubble_spawner.air_finished = 0; bubble_spawner.air_finished = 0;
bubble_spawner.owner = self; bubble_spawner.owner = self;
bubble_spawner.bubble_count = num_bubbles; bubble_spawner.bubble_count = num_bubbles;
return;
}; };
void() player_death_sound = { void() player_death_sound = {
@ -493,11 +500,12 @@ void() player_gib = {
void() player_die = { void() player_die = {
float i; 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.invisible_finished = 0; // don't die as eyes
self.invincible_finished = 0; self.invincible_finished = 0;
self.super_damage_finished = 0; self.super_damage_finished = 0;
self.radsuit_finished = 0; self.radsuit_finished = 0;
self.effects = 0;
self.modelindex = modelindex_player; // don't use eyes self.modelindex = modelindex_player; // don't use eyes
if(deathmatch || coop) { if(deathmatch || coop) {

View File

@ -1,4 +1,4 @@
// weapons.qc: weapon functions // p_weapons.qc: weapon functions
// called by worldspawn // called by worldspawn
void() wep_precache = { 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 launch_spike
@ -600,43 +637,6 @@ void(float ox) wep_fire_nail = {
self.punchangle_x = -2; self.punchangle_x = -2;
}; };
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);
};
void() superspike_touch = { void() superspike_touch = {
float rand; float rand;
if(other == self.owner) { if(other == self.owner) {

View File

@ -1,4 +1,4 @@
// models.qc: model information // v_models.qc: model information
/* /*
=============================================================================== ===============================================================================

View File

@ -1,4 +1,4 @@
// sprites.qc: sprite information // v_sprites.qc: sprite information
$spritename s_explod $spritename s_explod
$type vp_parallel $type vp_parallel

View File

@ -1,4 +1,6 @@
// buttons.qc: button and multiple button // w_buttons.qc: button and multiple button
void() button_return, button_wait;
void() button_wait = { void() button_wait = {
self.state = STATE_TOP; self.state = STATE_TOP;

View File

@ -1,4 +1,10 @@
// doors.qc: player-triggered moving brush entities // w_doors.qc: player-triggered moving brush entities
void() door_go_up;
void() fd_secret_done, fd_secret_move1, fd_secret_move2, fd_secret_move3,
fd_secret_move4, fd_secret_move5, fd_secret_move6;
/* /*
@ -98,7 +104,7 @@ void() door_fire = {
// play use key sound // play use key sound
if(self.items) { if(self.items) {
sound(self, CHAN_VOICE, self.noise4, 1, ATTN_NORM); sound(self, CHAN_ITEM, self.noise4, 1, ATTN_NORM);
} }
self.message = string_null; // no more message self.message = string_null; // no more message

View File

@ -1,4 +1,4 @@
// items.qc: items the player can pick up // w_items.qc: items the player can pick up
string() key_1_name = { string() key_1_name = {
switch(world.worldtype) { switch(world.worldtype) {
@ -113,42 +113,24 @@ float(entity e, float healamount, float ignore) ent_heal = {
return 1; return 1;
}; };
/*QUAKED item_health(.3 .3 1) (0 0 0) (32 32 32) rotten megahealth void() item_megahealth_rot = {
Health box. Normally gives 25 points. other = self.owner;
Rotten box heals 15 points,
Megahealth will add 100 health, then rot you down to your maximum health limit,
one point per second.
*/
void() item_health = { if(other.health > other.max_health) {
self.touch = health_touch; other.health = other.health - 1;
self.nextthink = time + 1;
if(self.spawnflags & HEALTH_ROTTEN) { return;
precache_model("maps/b_bh10.bsp");
precache_sound("items/r_item1.wav");
set_model(self, "maps/b_bh10.bsp");
self.noise = "items/r_item1.wav";
self.healamount = 15;
self.healtype = 0;
} else if(self.spawnflags & HEALTH_MEGA) {
precache_model("maps/b_bh100.bsp");
precache_sound("items/r_item2.wav");
set_model(self, "maps/b_bh100.bsp");
self.noise = "items/r_item2.wav";
self.healamount = 100;
self.healtype = 2;
} else {
precache_model("maps/b_bh25.bsp");
precache_sound("items/health1.wav");
set_model(self, "maps/b_bh25.bsp");
self.noise = "items/health1.wav";
self.healamount = 25;
self.healtype = 1;
} }
set_size(self, VEC_ORIGIN, '32 32 56');
start_item();
};
// it is possible for a player to die and respawn between rots, so don't
// just blindly subtract the flag off
other.items = other.items - (other.items & IT_SUPERHEALTH);
if(deathmatch == 1) { // deathmatch 2 is silly old rules
self.nextthink = time + 20;
self.think = sub_regen;
}
};
void() health_touch = { void() health_touch = {
float amount; float amount;
@ -194,23 +176,40 @@ void() health_touch = {
sub_use_targets(); // fire all targets / killtargets sub_use_targets(); // fire all targets / killtargets
}; };
void() item_megahealth_rot = { /*QUAKED item_health(.3 .3 1) (0 0 0) (32 32 32) rotten megahealth
other = self.owner; Health box. Normally gives 25 points.
Rotten box heals 15 points,
Megahealth will add 100 health, then rot you down to your maximum health limit,
one point per second.
*/
if(other.health > other.max_health) { void() item_health = {
other.health = other.health - 1; self.touch = health_touch;
self.nextthink = time + 1;
return; if(self.spawnflags & HEALTH_ROTTEN) {
} precache_model("maps/b_bh10.bsp");
precache_sound("items/r_item1.wav");
// it is possible for a player to die and respawn between rots, so don't set_model(self, "maps/b_bh10.bsp");
// just blindly subtract the flag off self.noise = "items/r_item1.wav";
other.items = other.items - (other.items & IT_SUPERHEALTH); self.healamount = 15;
self.healtype = 0;
if(deathmatch == 1) { // deathmatch 2 is silly old rules } else if(self.spawnflags & HEALTH_MEGA) {
self.nextthink = time + 20; precache_model("maps/b_bh100.bsp");
self.think = sub_regen; precache_sound("items/r_item2.wav");
set_model(self, "maps/b_bh100.bsp");
self.noise = "items/r_item2.wav";
self.healamount = 100;
self.healtype = 2;
} else {
precache_model("maps/b_bh25.bsp");
precache_sound("items/health1.wav");
set_model(self, "maps/b_bh25.bsp");
self.noise = "items/health1.wav";
self.healamount = 25;
self.healtype = 1;
} }
set_size(self, VEC_ORIGIN, '32 32 56');
start_item();
}; };
/* /*
@ -333,7 +332,10 @@ void(entity e) bound_ammo = {
float(float w) wep_rank_for_weapon = { float(float w) wep_rank_for_weapon = {
switch(w) { switch(w) {
case IT_LIGHTNING: return 1; case IT_LIGHTNING:
if(self.waterlevel <= 1) {
return 1;
}
case IT_ROCKET_LAUNCHER: return 2; case IT_ROCKET_LAUNCHER: return 2;
case IT_SUPER_NAILGUN: return 3; case IT_SUPER_NAILGUN: return 3;
case IT_GRENADE_LAUNCHER: return 4; case IT_GRENADE_LAUNCHER: return 4;
@ -451,11 +453,7 @@ void() weapon_touch = {
stemp = self; stemp = self;
self = other; self = other;
if(!deathmatch) {
self.weapon = new;
} else {
wep_deathmatch_weapon(old, new); wep_deathmatch_weapon(old, new);
}
wep_set_current_ammo(); wep_set_current_ammo();
@ -1156,11 +1154,7 @@ void() backpack_touch = {
self = other; self = other;
// change to the weapon // change to the weapon
if(!deathmatch) {
self.weapon = new;
} else {
wep_deathmatch_weapon(old, new); wep_deathmatch_weapon(old, new);
}
wep_set_current_ammo(); wep_set_current_ammo();
}; };

View File

@ -1,4 +1,4 @@
// misc.qc: various useful brushes // w_misc.qc: various useful brushes
/*QUAKED info_null(0 0.5 0) (-4 -4 -4) (4 4 4) /*QUAKED info_null(0 0.5 0) (-4 -4 -4) (4 4 4)
Used as a positional target for spotlights, etc. Used as a positional target for spotlights, etc.
@ -146,6 +146,8 @@ void() light_flame_small_white = {
//============================================================================ //============================================================================
void() fire_fly, fire_touch;
/*QUAKED misc_fireball(0 .5 .8) (-8 -8 -8) (8 8 8) /*QUAKED misc_fireball(0 .5 .8) (-8 -8 -8) (8 8 8)
Lava Balls Lava Balls
*/ */
@ -153,7 +155,7 @@ Lava Balls
void() misc_fireball = { void() misc_fireball = {
precache_model("progs/lavaball.mdl"); precache_model("progs/lavaball.mdl");
self.classname = "fireball"; self.classname = "fireball";
self.nextthink = time + (random() * 5); self.nextthink = time + 0.1 + (random() * 5);
self.think = fire_fly; self.think = fire_fly;
if(!self.speed) { if(!self.speed) {
self.speed = 1000; self.speed = 1000;
@ -189,10 +191,7 @@ void() fire_touch = {
//============================================================================ //============================================================================
void() barrel_explode = { void() barrel_damage = {
self.takedamage = DAMAGE_NO;
self.classname = "explo_box";
// did say self.owner
ent_radius_damage(self, self, 160, world); ent_radius_damage(self, self, 160, world);
sound(self, CHAN_VOICE, "weapons/r_exp3.wav", 1, ATTN_NORM); sound(self, CHAN_VOICE, "weapons/r_exp3.wav", 1, ATTN_NORM);
particle(self.origin, VEC_ORIGIN, 75, 255); particle(self.origin, VEC_ORIGIN, 75, 255);
@ -201,6 +200,13 @@ void() barrel_explode = {
become_explosion(); become_explosion();
}; };
void() barrel_explode = {
self.takedamage = DAMAGE_NO;
self.classname = "explo_box";
self.nextthink = time + 0.1;
self.think = barrel_damage;
};
/*QUAKED misc_explobox(0 .5 .8) (0 0 0) (32 32 64) /*QUAKED misc_explobox(0 .5 .8) (0 0 0) (32 32 64)
TESTING THING TESTING THING
@ -315,6 +321,8 @@ void() trap_shooter = {
=============================================================================== ===============================================================================
*/ */
void() bubble_remove, make_bubbles;
/*QUAKED air_bubbles(0 .5 .8) (-8 -8 -8) (8 8 8) /*QUAKED air_bubbles(0 .5 .8) (-8 -8 -8) (8 8 8)
testing air bubbles testing air bubbles

View File

@ -1,4 +1,9 @@
// plats.qc: moving platforms // w_plats.qc: moving platforms
void() plat_center_touch, plat_crush, plat_go_down, plat_go_up,
plat_outside_touch, plat_trigger_use;
void() train_wait;
void() plat_spawn_inside_trigger = { void() plat_spawn_inside_trigger = {
entity trigger; entity trigger;
@ -206,23 +211,6 @@ void() train_blocked = {
self.attack_finished = time + 0.5; self.attack_finished = time + 0.5;
ent_damage(other, self, self, self.dmg); ent_damage(other, self, self, self.dmg);
}; };
void() train_use = {
if(self.think != func_train_find) {
return; // already activated
}
train_next();
};
void() train_wait = {
if(self.wait) {
self.nextthink = self.ltime + self.wait;
sound(self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
} else {
self.nextthink = self.ltime + 0.1;
}
self.think = train_next;
};
void() train_next = { void() train_next = {
entity targ; entity targ;
@ -254,6 +242,24 @@ void() func_train_find = {
} }
}; };
void() train_use = {
if(self.think != func_train_find) {
return; // already activated
}
train_next();
};
void() train_wait = {
if(self.wait) {
self.nextthink = self.ltime + self.wait;
sound(self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
} else {
self.nextthink = self.ltime + 0.1;
}
self.think = train_next;
};
/*QUAKED func_train(0 .5 .8) ? /*QUAKED func_train(0 .5 .8) ?
Trains are moving platforms that players can ride. Trains are moving platforms that players can ride.
The targets origin specifies the min point of the train at each corner. The targets origin specifies the min point of the train at each corner.

View File

@ -1,4 +1,4 @@
// triggers.qc: triggerable entities // w_triggers.qc: triggerable entities
void() trigger_reactivate = { void() trigger_reactivate = {
self.solid = SOLID_TRIGGER; self.solid = SOLID_TRIGGER;
@ -286,14 +286,21 @@ void() tdeath_touch = {
// frag anyone who teleports in on top of an invincible player // frag anyone who teleports in on top of an invincible player
if(other.classname == "player") { if(other.classname == "player") {
if(other.invincible_finished > time) {
self.classname = "teledeath2";
}
if(self.owner.classname != "player") { if(self.owner.classname != "player") {
// other monsters explode themselves
ent_damage(self.owner, self, self, 50000); ent_damage(self.owner, self, self, 50000);
return; return;
} }
if(other.invincible_finished > time) {
if(self.owner.invincible_finished > time) {
self.classname = "teledeath3";
other.invincible_finished = 0;
ent_damage(other, self, self, 50000);
} else {
self.classname = "teledeath2";
ent_damage(self.owner, self, self, 50000);
}
return;
}
} }
if(other.health) { if(other.health) {
@ -342,14 +349,17 @@ void() teleport_touch = {
sub_use_targets(); sub_use_targets();
t = find(world, targetname, self.target);
if(!t ||
t.classname != "info_teleport_destination" &&
t.classname != "misc_teleporttrain") {
print_dbg("object error in teleport_touch: no target\n");
return;
}
// put a tfog where the player was // put a tfog where the player was
spawn_tfog(other.origin); spawn_tfog(other.origin);
t = find(world, targetname, self.target);
if(!t) {
error_obj("couldn't find target");
}
// spawn a tfog flash in front of the destination // spawn a tfog flash in front of the destination
make_vectors(t.mangle); make_vectors(t.mangle);
org = t.origin + 32 * v_forward; org = t.origin + 32 * v_forward;
@ -485,17 +495,14 @@ void() trigger_onlyregistered = {
//============================================================================ //============================================================================
void() hurt_on = {
self.solid = SOLID_TRIGGER;
self.nextthink = -1;
};
void() hurt_touch = { void() hurt_touch = {
if(other.takedamage) { if(other.takedamage) {
self.solid = SOLID_NOT; if(time != self.hurt_together_time && time < self.hurt_nextthink) {
return;
}
ent_damage(other, self, self, self.dmg); ent_damage(other, self, self, self.dmg);
self.think = hurt_on; self.hurt_together_time = time;
self.nextthink = time + 1; self.hurt_nextthink = time + 1;
} }
return; return;

View File

@ -1,4 +1,6 @@
// world.qc: basic entry point functions // w_world.qc: basic entry point functions
void() init_body_queue;
void() main = { void() main = {
}; };

3
todo
View File

@ -4,7 +4,7 @@ none
refactoring: refactoring:
add expansion pack entities all done
core features: core features:
@ -17,6 +17,7 @@ indicators for where other players are
extraneous features: extraneous features:
add expansion pack entities
emotes emotes
player sound effect option player sound effect option
players shoot through eachother (teamplay 4?) players shoot through eachother (teamplay 4?)

View File

@ -56,7 +56,7 @@ set reps \
SUB_Remove sub_remove \ SUB_Remove sub_remove \
T_Heal ent_heal \ T_Heal ent_heal \
CanHeal can_heal \ CanHeal can_heal \
CanDamage can_damage \ CanDamage ent_can_damage \
T_Damage ent_damage \ T_Damage ent_damage \
T_RadiusDamage ent_radius_damage \ T_RadiusDamage ent_radius_damage \
T_MissileTouch ent_missile_touch \ T_MissileTouch ent_missile_touch \