diff --git a/maps/fiend_test.bsp b/maps/fiend_test.bsp new file mode 100644 index 0000000..7f5a230 Binary files /dev/null and b/maps/fiend_test.bsp differ diff --git a/maps/fiend_test.lit b/maps/fiend_test.lit new file mode 100644 index 0000000..ba10d1a Binary files /dev/null and b/maps/fiend_test.lit differ 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 \