From e6221792a43286d31b76ff9852f5aefe18f87a25 Mon Sep 17 00:00:00 2001 From: Alison Watson Date: Sat, 21 Sep 2019 15:29:42 -0400 Subject: [PATCH] implement various fixes and refactorings --- maps/fiend_test.bsp | Bin 0 -> 97024 bytes maps/fiend_test.lit | Bin 0 -> 17540 bytes progs.src | 64 +++---- source/ai.qc | 63 ++---- source/{fight.qc => ai_fight.qc} | 17 +- source/{monsters.qc => ai_monsters.qc} | 21 +- source/{subs.qc => ai_subs.qc} | 2 +- source/{combat.qc => c_combat.qc} | 50 ++--- source/{common.qc => c_common.qc} | 13 +- source/{defs.qc => c_defs.qc} | 212 +++++++++------------ source/{soldier.qc => m_army.qc} | 4 +- source/{boss.qc => m_boss.qc} | 6 +- source/{demon.qc => m_demon.qc} | 36 ++-- source/{dog.qc => m_dog.qc} | 12 +- source/{enforcer.qc => m_enforcer.qc} | 2 +- source/{fish.qc => m_fish.qc} | 19 +- source/{hknight.qc => m_hknight.qc} | 4 +- source/{knight.qc => m_knight.qc} | 15 +- source/{ogre.qc => m_ogre.qc} | 22 ++- source/{oldone.qc => m_oldone.qc} | 20 +- source/{shalrath.qc => m_shalrath.qc} | 4 +- source/{shambler.qc => m_shambler.qc} | 42 ++-- source/{tarbaby.qc => m_tarbaby.qc} | 4 +- source/{wizard.qc => m_wizard.qc} | 4 +- source/{zombie.qc => m_zombie.qc} | 7 +- source/{client.qc => p_client.qc} | 116 ++++++----- source/{player.qc => p_player.qc} | 22 ++- source/{weapons.qc => p_weapons.qc} | 76 ++++---- source/{models.qc => v_models.qc} | 2 +- source/{sprites.qc => v_sprites.qc} | 2 +- source/{buttons.qc => w_buttons.qc} | 4 +- source/{doors.qc => w_doors.qc} | 10 +- source/{items.qc => w_items.qc} | 114 ++++++----- source/{misc.qc => w_misc.qc} | 20 +- source/{plats.qc => w_plats.qc} | 42 ++-- source/{triggers.qc => w_triggers.qc} | 43 +++-- source/{world.qc => w_world.qc} | 4 +- todo | 3 +- fixsrc.rb => tools/fixsrc.rb | 0 fixsrcnames.fish => tools/fixsrcnames.fish | 2 +- 40 files changed, 560 insertions(+), 543 deletions(-) create mode 100644 maps/fiend_test.bsp create mode 100644 maps/fiend_test.lit rename source/{fight.qc => ai_fight.qc} (90%) rename source/{monsters.qc => ai_monsters.qc} (89%) rename source/{subs.qc => ai_subs.qc} (99%) rename source/{combat.qc => c_combat.qc} (86%) rename source/{common.qc => c_common.qc} (91%) rename source/{defs.qc => c_defs.qc} (91%) rename source/{soldier.qc => m_army.qc} (99%) rename source/{boss.qc => m_boss.qc} (99%) rename source/{demon.qc => m_demon.qc} (95%) rename source/{dog.qc => m_dog.qc} (98%) rename source/{enforcer.qc => m_enforcer.qc} (99%) rename source/{fish.qc => m_fish.qc} (94%) rename source/{hknight.qc => m_hknight.qc} (99%) rename source/{knight.qc => m_knight.qc} (97%) rename source/{ogre.qc => m_ogre.qc} (97%) rename source/{oldone.qc => m_oldone.qc} (96%) rename source/{shalrath.qc => m_shalrath.qc} (98%) rename source/{shambler.qc => m_shambler.qc} (94%) rename source/{tarbaby.qc => m_tarbaby.qc} (99%) rename source/{wizard.qc => m_wizard.qc} (99%) rename source/{zombie.qc => m_zombie.qc} (99%) rename source/{client.qc => p_client.qc} (98%) rename source/{player.qc => p_player.qc} (97%) rename source/{weapons.qc => p_weapons.qc} (99%) rename source/{models.qc => v_models.qc} (99%) rename source/{sprites.qc => v_sprites.qc} (92%) rename source/{buttons.qc => w_buttons.qc} (97%) rename source/{doors.qc => w_doors.qc} (98%) rename source/{items.qc => w_items.qc} (94%) rename source/{misc.qc => w_misc.qc} (98%) rename source/{plats.qc => w_plats.qc} (97%) rename source/{triggers.qc => w_triggers.qc} (95%) rename source/{world.qc => w_world.qc} (99%) rename fixsrc.rb => tools/fixsrc.rb (100%) rename fixsrcnames.fish => tools/fixsrcnames.fish (99%) diff --git a/maps/fiend_test.bsp b/maps/fiend_test.bsp new file mode 100644 index 0000000000000000000000000000000000000000..7f5a230d701f32604c0ba691824d5083f1a8bf3a GIT binary patch literal 97024 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 F{eKMEkOu$& literal 0 HcmV?d00001 diff --git a/progs.src b/progs.src index 0dbf056..b71e377 100644 --- a/progs.src +++ b/progs.src @@ -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 diff --git a/source/ai.qc b/source/ai.qc index 0548105..fa0716a 100644 --- a/source/ai.qc +++ b/source/ai.qc @@ -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 diff --git a/source/fight.qc b/source/ai_fight.qc similarity index 90% rename from source/fight.qc rename to source/ai_fight.qc index 44c7a52..51d166b 100644 --- a/source/fight.qc +++ b/source/ai_fight.qc @@ -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; diff --git a/source/monsters.qc b/source/ai_monsters.qc similarity index 89% rename from source/monsters.qc rename to source/ai_monsters.qc index dea0bf8..b800ea6 100644 --- a/source/monsters.qc +++ b/source/ai_monsters.qc @@ -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 @@ // // }; +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; }; diff --git a/source/subs.qc b/source/ai_subs.qc similarity index 99% rename from source/subs.qc rename to source/ai_subs.qc index a8bd16a..d40a13f 100644 --- a/source/subs.qc +++ b/source/ai_subs.qc @@ -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 = {}; diff --git a/source/combat.qc b/source/c_combat.qc similarity index 86% rename from source/combat.qc rename to source/c_combat.qc index 2ca5b8e..61ff90a 100644 --- a/source/combat.qc +++ b/source/c_combat.qc @@ -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 { diff --git a/source/common.qc b/source/c_common.qc similarity index 91% rename from source/common.qc rename to source/c_common.qc index 455385e..b7a147f 100644 --- a/source/common.qc +++ b/source/c_common.qc @@ -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() diff --git a/source/defs.qc b/source/c_defs.qc similarity index 91% rename from source/defs.qc rename to source/c_defs.qc index 5f3f73b..7d51160 100644 --- a/source/defs.qc +++ b/source/c_defs.qc @@ -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 diff --git a/source/soldier.qc b/source/m_army.qc similarity index 99% rename from source/soldier.qc rename to source/m_army.qc index 29ebeae..d0b5ab3 100644 --- a/source/soldier.qc +++ b/source/m_army.qc @@ -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; + //============================================================================= /* diff --git a/source/boss.qc b/source/m_boss.qc similarity index 99% rename from source/boss.qc rename to source/m_boss.qc index cf4260b..304261d 100644 --- a/source/boss.qc +++ b/source/m_boss.qc @@ -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); }; diff --git a/source/demon.qc b/source/m_demon.qc similarity index 95% rename from source/demon.qc rename to source/m_demon.qc index 8a0386e..d334870 100644 --- a/source/demon.qc +++ b/source/m_demon.qc @@ -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; } diff --git a/source/dog.qc b/source/m_dog.qc similarity index 98% rename from source/dog.qc rename to source/m_dog.qc index 36d6caf..84c6611 100644 --- a/source/dog.qc +++ b/source/m_dog.qc @@ -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; }; /* diff --git a/source/enforcer.qc b/source/m_enforcer.qc similarity index 99% rename from source/enforcer.qc rename to source/m_enforcer.qc index 93772b6..3def202 100644 --- a/source/enforcer.qc +++ b/source/m_enforcer.qc @@ -1,4 +1,4 @@ -// enforcer.qc: Enforcer +// m_enforcer.qc: Enforcer $cd id1 / models / enforcer $origin 0 - 6 24 diff --git a/source/fish.qc b/source/m_fish.qc similarity index 94% rename from source/fish.qc rename to source/m_fish.qc index 2cfa801..74f4f47 100644 --- a/source/fish.qc +++ b/source/m_fish.qc @@ -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; diff --git a/source/hknight.qc b/source/m_hknight.qc similarity index 99% rename from source/hknight.qc rename to source/m_hknight.qc index 5013451..576190e 100644 --- a/source/hknight.qc +++ b/source/m_hknight.qc @@ -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); diff --git a/source/knight.qc b/source/m_knight.qc similarity index 97% rename from source/knight.qc rename to source/m_knight.qc index 5cb37ba..df03810 100644 --- a/source/knight.qc +++ b/source/m_knight.qc @@ -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 = { diff --git a/source/ogre.qc b/source/m_ogre.qc similarity index 97% rename from source/ogre.qc rename to source/m_ogre.qc index 01c5e99..1b95022 100644 --- a/source/ogre.qc +++ b/source/m_ogre.qc @@ -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);}; diff --git a/source/oldone.qc b/source/m_oldone.qc similarity index 96% rename from source/oldone.qc rename to source/m_oldone.qc index 620aa20..f3c6d02 100644 --- a/source/oldone.qc +++ b/source/m_oldone.qc @@ -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; diff --git a/source/shalrath.qc b/source/m_shalrath.qc similarity index 98% rename from source/shalrath.qc rename to source/m_shalrath.qc index 5e5b389..5cd47b7 100644 --- a/source/shalrath.qc +++ b/source/m_shalrath.qc @@ -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 ] { diff --git a/source/shambler.qc b/source/m_shambler.qc similarity index 94% rename from source/shambler.qc rename to source/m_shambler.qc index 606a950..8a20b13 100644 --- a/source/shambler.qc +++ b/source/m_shambler.qc @@ -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; diff --git a/source/tarbaby.qc b/source/m_tarbaby.qc similarity index 99% rename from source/tarbaby.qc rename to source/m_tarbaby.qc index 299ebf5..d7c1ce1 100644 --- a/source/tarbaby.qc +++ b/source/m_tarbaby.qc @@ -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();}; diff --git a/source/wizard.qc b/source/m_wizard.qc similarity index 99% rename from source/wizard.qc rename to source/m_wizard.qc index 41a1d44..284f5f1 100644 --- a/source/wizard.qc +++ b/source/m_wizard.qc @@ -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; + /* ============================================================================== diff --git a/source/zombie.qc b/source/m_zombie.qc similarity index 99% rename from source/zombie.qc rename to source/m_zombie.qc index 3ad12ab..ca19f4e 100644 --- a/source/zombie.qc +++ b/source/m_zombie.qc @@ -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 } diff --git a/source/client.qc b/source/p_client.qc similarity index 98% rename from source/client.qc rename to source/p_client.qc index 0190140..629d50f 100644 --- a/source/client.qc +++ b/source/p_client.qc @@ -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); diff --git a/source/player.qc b/source/p_player.qc similarity index 97% rename from source/player.qc rename to source/p_player.qc index 4a71d4e..f7d0c32 100644 --- a/source/player.qc +++ b/source/p_player.qc @@ -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) { diff --git a/source/weapons.qc b/source/p_weapons.qc similarity index 99% rename from source/weapons.qc rename to source/p_weapons.qc index a0314d7..8bb399e 100644 --- a/source/weapons.qc +++ b/source/p_weapons.qc @@ -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 @@ -600,43 +637,6 @@ void(float ox) wep_fire_nail = { 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 = { float rand; if(other == self.owner) { diff --git a/source/models.qc b/source/v_models.qc similarity index 99% rename from source/models.qc rename to source/v_models.qc index 5b65153..c09f3cd 100644 --- a/source/models.qc +++ b/source/v_models.qc @@ -1,4 +1,4 @@ -// models.qc: model information +// v_models.qc: model information /* =============================================================================== diff --git a/source/sprites.qc b/source/v_sprites.qc similarity index 92% rename from source/sprites.qc rename to source/v_sprites.qc index eb50563..1846835 100644 --- a/source/sprites.qc +++ b/source/v_sprites.qc @@ -1,4 +1,4 @@ -// sprites.qc: sprite information +// v_sprites.qc: sprite information $spritename s_explod $type vp_parallel diff --git a/source/buttons.qc b/source/w_buttons.qc similarity index 97% rename from source/buttons.qc rename to source/w_buttons.qc index 2d048db..7ac46e2 100644 --- a/source/buttons.qc +++ b/source/w_buttons.qc @@ -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 = { self.state = STATE_TOP; diff --git a/source/doors.qc b/source/w_doors.qc similarity index 98% rename from source/doors.qc rename to source/w_doors.qc index 0d47562..fe7300f 100644 --- a/source/doors.qc +++ b/source/w_doors.qc @@ -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 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 diff --git a/source/items.qc b/source/w_items.qc similarity index 94% rename from source/items.qc rename to source/w_items.qc index 8a5a481..fcacaee 100644 --- a/source/items.qc +++ b/source/w_items.qc @@ -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 = { switch(world.worldtype) { @@ -113,42 +113,24 @@ float(entity e, float healamount, float ignore) ent_heal = { return 1; }; -/*QUAKED item_health(.3 .3 1) (0 0 0) (32 32 32) rotten megahealth -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. -*/ +void() item_megahealth_rot = { + other = self.owner; -void() item_health = { - self.touch = health_touch; - - if(self.spawnflags & HEALTH_ROTTEN) { - 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; + if(other.health > other.max_health) { + other.health = other.health - 1; + self.nextthink = time + 1; + return; } - 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 = { float amount; @@ -194,23 +176,40 @@ void() health_touch = { sub_use_targets(); // fire all targets / killtargets }; -void() item_megahealth_rot = { - other = self.owner; +/*QUAKED item_health(.3 .3 1) (0 0 0) (32 32 32) rotten megahealth +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) { - other.health = other.health - 1; - self.nextthink = time + 1; - return; - } - - // 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() item_health = { + self.touch = health_touch; + + if(self.spawnflags & HEALTH_ROTTEN) { + 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(); }; /* @@ -333,7 +332,10 @@ void(entity e) bound_ammo = { float(float w) wep_rank_for_weapon = { switch(w) { - case IT_LIGHTNING: return 1; + case IT_LIGHTNING: + if(self.waterlevel <= 1) { + return 1; + } case IT_ROCKET_LAUNCHER: return 2; case IT_SUPER_NAILGUN: return 3; case IT_GRENADE_LAUNCHER: return 4; @@ -451,11 +453,7 @@ void() weapon_touch = { stemp = self; self = other; - if(!deathmatch) { - self.weapon = new; - } else { - wep_deathmatch_weapon(old, new); - } + wep_deathmatch_weapon(old, new); wep_set_current_ammo(); @@ -1156,11 +1154,7 @@ void() backpack_touch = { self = other; // change to the weapon - if(!deathmatch) { - self.weapon = new; - } else { - wep_deathmatch_weapon(old, new); - } + wep_deathmatch_weapon(old, new); wep_set_current_ammo(); }; diff --git a/source/misc.qc b/source/w_misc.qc similarity index 98% rename from source/misc.qc rename to source/w_misc.qc index f735216..15e2cc4 100644 --- a/source/misc.qc +++ b/source/w_misc.qc @@ -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) 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) Lava Balls */ @@ -153,7 +155,7 @@ Lava Balls void() misc_fireball = { precache_model("progs/lavaball.mdl"); self.classname = "fireball"; - self.nextthink = time + (random() * 5); + self.nextthink = time + 0.1 + (random() * 5); self.think = fire_fly; if(!self.speed) { self.speed = 1000; @@ -189,10 +191,7 @@ void() fire_touch = { //============================================================================ -void() barrel_explode = { - self.takedamage = DAMAGE_NO; - self.classname = "explo_box"; - // did say self.owner +void() barrel_damage = { ent_radius_damage(self, self, 160, world); sound(self, CHAN_VOICE, "weapons/r_exp3.wav", 1, ATTN_NORM); particle(self.origin, VEC_ORIGIN, 75, 255); @@ -201,6 +200,13 @@ void() barrel_explode = { 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) 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) testing air bubbles diff --git a/source/plats.qc b/source/w_plats.qc similarity index 97% rename from source/plats.qc rename to source/w_plats.qc index bbc9b0b..afa4ecf 100644 --- a/source/plats.qc +++ b/source/w_plats.qc @@ -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 = { entity trigger; @@ -206,23 +211,6 @@ void() train_blocked = { self.attack_finished = time + 0.5; 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 = { 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) ? Trains are moving platforms that players can ride. The targets origin specifies the min point of the train at each corner. diff --git a/source/triggers.qc b/source/w_triggers.qc similarity index 95% rename from source/triggers.qc rename to source/w_triggers.qc index c425395..6a9c254 100644 --- a/source/triggers.qc +++ b/source/w_triggers.qc @@ -1,4 +1,4 @@ -// triggers.qc: triggerable entities +// w_triggers.qc: triggerable entities void() trigger_reactivate = { self.solid = SOLID_TRIGGER; @@ -286,14 +286,21 @@ void() tdeath_touch = { // frag anyone who teleports in on top of an invincible player if(other.classname == "player") { - if(other.invincible_finished > time) { - self.classname = "teledeath2"; - } if(self.owner.classname != "player") { - // other monsters explode themselves ent_damage(self.owner, self, self, 50000); 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) { @@ -342,14 +349,17 @@ void() teleport_touch = { 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 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 make_vectors(t.mangle); 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 = { 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); - self.think = hurt_on; - self.nextthink = time + 1; + self.hurt_together_time = time; + self.hurt_nextthink = time + 1; } return; diff --git a/source/world.qc b/source/w_world.qc similarity index 99% rename from source/world.qc rename to source/w_world.qc index 52bf738..8d4fedf 100644 --- a/source/world.qc +++ b/source/w_world.qc @@ -1,4 +1,6 @@ -// world.qc: basic entry point functions +// w_world.qc: basic entry point functions + +void() init_body_queue; void() main = { }; diff --git a/todo b/todo index 6504e10..c495ede 100644 --- a/todo +++ b/todo @@ -4,7 +4,7 @@ none refactoring: -add expansion pack entities +all done core features: @@ -17,6 +17,7 @@ indicators for where other players are extraneous features: +add expansion pack entities emotes player sound effect option players shoot through eachother (teamplay 4?) diff --git a/fixsrc.rb b/tools/fixsrc.rb similarity index 100% rename from fixsrc.rb rename to tools/fixsrc.rb diff --git a/fixsrcnames.fish b/tools/fixsrcnames.fish similarity index 99% rename from fixsrcnames.fish rename to tools/fixsrcnames.fish index 05408af..ac373ad 100644 --- a/fixsrcnames.fish +++ b/tools/fixsrcnames.fish @@ -56,7 +56,7 @@ set reps \ SUB_Remove sub_remove \ T_Heal ent_heal \ CanHeal can_heal \ - CanDamage can_damage \ + CanDamage ent_can_damage \ T_Damage ent_damage \ T_RadiusDamage ent_radius_damage \ T_MissileTouch ent_missile_touch \