Compare commits

...

3 Commits

41 changed files with 681 additions and 585 deletions

View File

@ -9,12 +9,24 @@ alias pronoun_ze_hir "impulse 27"
alias pronoun_ze_zir "impulse 28"
alias spectate "impulse 13"
alias reject_challenge "impulse 14"
set sc_cheats 0
set sc_lives 0
set sc_dist_ammo 0
set sc_challenge 0
bind p "reject_challenge"
echo "To change your pronouns in-game use one of the pronoun_ commands."
echo "You can get a list by typing 'pronoun_' and pressing tab."
echo
echo "If the server supports it, you can also put (possessive) after your"
echo "name, and it will be automatically detected. Example:"
echo "_cl_name Marrub (their)"
echo
echo "To reject travel to another level while sc_challenge is set, you"
echo "may type 'reject_challenge' into the console, which by default is"
echo "bound to 'p'."
// EOF

BIN
maps/fiend_test.bsp Normal file

Binary file not shown.

BIN
maps/fiend_test.lit Normal file

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,44 @@
// client.qc: player-adjacent functions
// p_client.qc: player-adjacent functions
void() impulse_commands;
/*
=============================================================================
QUAKED FUNCTIONS
=============================================================================
*/
/*QUAKED info_player_start(1 0 0) (-16 -16 -24) (16 16 24)
The normal starting point for a level.
*/
void() info_player_start = {
};
/*QUAKED info_player_start2(1 0 0) (-16 -16 -24) (16 16 24)
Only used on start map for the return point from an episode.
*/
void() info_player_start2 = {
};
/*
saved out by quaked in region mode
*/
void() testplayerstart = {
};
/*QUAKED info_player_deathmatch(1 0 1) (-16 -16 -24) (16 16 24)
potential spawning position for deathmatch games
*/
void() info_player_deathmatch = {
};
/*QUAKED info_player_coop(1 0 1) (-16 -16 -24) (16 16 24)
potential spawning position for coop games
*/
void() info_player_coop = {
};
string(float pro) pronoun_subject = {
switch(pro) {
@ -85,10 +125,8 @@ void() SetNewParms = {
void() decode_level_parms = {
float ofs, ofs2, pro;
if(serverflags) {
if(world.model == "maps/start.bsp") {
SetNewParms(); // take away all stuff on starting new episode
}
if(!deathmatch && world.model == "maps/start.bsp") {
SetNewParms(); // take away all stuff on starting new episode
}
self.items = parm1;
@ -257,7 +295,7 @@ void() intermission_exit = {
}
intermission_exittime = time + 1;
intermission_running = intermission_running + 1;
intermission_running++;
//
// run some text if at the end of an episode
@ -371,22 +409,7 @@ void() execute_changelevel = {
write_byte(MSG_ALL, SVC_INTERMISSION);
};
void() changelevel_touch = {
entity pos;
if(other.classname != "player") {
return;
}
if(cvar("noexit") == 1 || (cvar("noexit") == 2 && mapname != "start")) {
ent_damage(other, self, self, 50000);
return;
}
if(coop || deathmatch) {
print_all(other.netname, " exited the level\n");
}
void() changelevel_finish = {
nextmap = self.map;
sub_use_targets();
@ -404,6 +427,75 @@ void() changelevel_touch = {
self.nextthink = time + 0.1;
};
void() set_challenge_reject = {
if(changelevel_challenge == CHALLENGE_ACTIVE) {
changelevel_challenge = CHALLENGE_REJECTED;
challenge_rejecter = self.netname;
}
};
void() changelevel_think = {
entity pl;
if(changelevel_challenge == CHALLENGE_REJECTED) {
pl = find(world, classname, "player");
while(pl != world) {
print_center(pl, "The travel was canceled by\n", challenge_rejecter);
pl = find(pl, classname, "player");
}
changelevel_challenge = CHALLENGE_NONE;
self.netname = string_null;
self.aflag = 0;
return;
}
if(self.aflag == 0) {
changelevel_finish();
return;
}
pl = find(world, classname, "player");
while(pl != world) {
print_center(pl,
self.netname,
"\ninitiated travel to\n",
self.map, "\n\n",
ftos(self.aflag), " seconds to travel");
pl = find(pl, classname, "player");
}
sound(self, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NONE);
self.aflag--;
self.nextthink = time + 1;
};
void() changelevel_touch = {
entity pos;
if(other.classname != "player" || changelevel_challenge) {
return;
}
if(cvar("noexit") == 1 || (cvar("noexit") == 2 && mapname != "start")) {
ent_damage(other, self, self, 50000);
return;
}
if(sc_challenge) {
changelevel_challenge = CHALLENGE_ACTIVE;
self.netname = other.netname;
self.aflag = 10;
self.think = changelevel_think;
self.nextthink = time + 0.1;
} else {
if(coop || deathmatch) {
print_all(other.netname, " exited the level\n");
}
changelevel_finish();
}
};
/*QUAKED trigger_changelevel(0.5 0.5 0.5) ? NO_INTERMISSION
When the player touches this, they get sent to the map listed in the "map" variable. Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display stats.
*/
@ -442,7 +534,6 @@ void() become_spectator = {
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_NOCLIP;
self.flags |= FL_NOTARGET;
self.deadflag = DEAD_DEAD;
self.view_ofs = VEC_ORIGIN;
self.frame = 0;
self.modelindex = modelindex_eyes;
@ -525,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;
}
@ -567,7 +658,7 @@ void() PutClientInServer = {
respawned = player_respawned;
player_respawned = FALSE;
if(sf_lives) {
if(sc_lives) {
if(respawned) {
self.lives--;
print_all(self.netname, " has ");
@ -581,8 +672,8 @@ void() PutClientInServer = {
print_all(ftos(self.lives), " lives left\n");
}
} else if(self.lives == 0) {
self.lives = sf_lives;
print_dbg("lives reset to ", ftos(sf_lives), "\n");
self.lives = sc_lives;
print_dbg("lives reset to ", ftos(sc_lives), "\n");
}
} else {
self.lives = 1;
@ -621,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");
@ -635,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();
@ -646,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 = {
};
/*
===============================================================================
@ -1127,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();
}
@ -1201,7 +1256,7 @@ void() ClientDisconnect = {
};
void() cheat = {
if(((deathmatch || coop) && !sf_cheats) || self.spectating) {
if(((deathmatch || coop) && !sc_cheats) || self.spectating) {
return;
}
@ -1226,7 +1281,7 @@ void() cheat = {
};
void() cheat_quad = {
if(((deathmatch || coop) && !sf_cheats) || self.spectating) {
if(((deathmatch || coop) && !sc_cheats) || self.spectating) {
return;
}
@ -1279,11 +1334,12 @@ void() impulse_commands = {
change_pronoun(self.impulse - 20);
} else {
switch(self.impulse) {
case 9: cheat(); break;
case 10: wep_cycle_weapon(); break;
case 11: cheat_quad(); break;
case 9: cheat(); break;
case 10: wep_cycle_weapon(); break;
case 11: cheat_quad(); break;
case 12: wep_cycle_weapon_reverse(); break;
case 13: spectate(); break;
case 13: spectate(); break;
case 14: set_challenge_reject(); break;
}
}
@ -1291,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;
};
@ -1302,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--;
@ -1348,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:
@ -1628,6 +1693,9 @@ void(entity targ, entity attacker) client_obituary = {
case "teledeath2":
did_message = obit_teledeath2(targ, attacker);
break;
case "teledeath3":
did_message = obit_teledeath3(targ, attacker);
break;
case "player":
if(targ == attacker) {
did_message = obit_suicide(targ, attacker);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,10 @@
// doors.qc: player-triggered moving brush entities
// w_doors.qc: player-triggered moving brush entities
void() door_go_up;
void() fd_secret_done, fd_secret_move1, fd_secret_move2, fd_secret_move3,
fd_secret_move4, fd_secret_move5, fd_secret_move6;
/*
@ -98,7 +104,7 @@ void() door_fire = {
// play use key sound
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

View File

@ -1,4 +1,4 @@
// items.qc: items the player can pick up
// w_items.qc: items the player can pick up
string() key_1_name = {
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();
@ -569,7 +567,7 @@ AMMO
void(.float ammo, float max) distribute_ammo = {
entity pl, stemp;
if(sf_dist_ammo) {
if(sc_dist_ammo) {
pl = find(world, classname, "player");
while(pl != world) {
pl.ammo += self.aflag;
@ -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();
};

View File

@ -1,4 +1,4 @@
// misc.qc: various useful brushes
// w_misc.qc: various useful brushes
/*QUAKED info_null(0 0.5 0) (-4 -4 -4) (4 4 4)
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

View File

@ -1,4 +1,9 @@
// plats.qc: moving platforms
// w_plats.qc: moving platforms
void() plat_center_touch, plat_crush, plat_go_down, plat_go_up,
plat_outside_touch, plat_trigger_use;
void() train_wait;
void() plat_spawn_inside_trigger = {
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.

View File

@ -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;

View File

@ -1,4 +1,6 @@
// world.qc: basic entry point functions
// w_world.qc: basic entry point functions
void() init_body_queue;
void() main = {
};
@ -192,14 +194,16 @@ void() StartFrame = {
framecount = framecount + 1;
if(ext_con_set) {
sf_cheats = cvar("sc_cheats");
sf_lives = cvar("sc_lives");
sf_dist_ammo = cvar("sc_dist_ammo");
sc_cheats = cvar("sc_cheats");
sc_lives = cvar("sc_lives");
sc_dist_ammo = cvar("sc_dist_ammo");
sc_challenge = cvar("sc_challenge");
} else {
temp1flag = cvar("temp1");
sf_cheats = (temp1flag & SF_CHEATS) != 0;
sf_lives = bit_shift_right(temp1flag & SF_LIVES_MSK, SF_LIVES_BEG);
sf_dist_ammo = (temp1flag & SF_DIST_AMMO) != 0;
sc_cheats = (temp1flag & SC_CHEATS) != 0;
sc_lives = bit_shift_right(temp1flag & SC_LIVES_MSK, SC_LIVES_BEG);
sc_dist_ammo = (temp1flag & SC_DIST_AMMO) != 0;
sc_challenge = (temp1flag & SC_CHALLENGE) != 0;
}
if(all_players_are_dead) {

5
todo
View File

@ -4,7 +4,7 @@ none
refactoring:
add expansion pack entities
all done
core features:
@ -14,10 +14,10 @@ useful features:
configurable enemy stats
indicators for where other players are
users can cancel map ends ("<name> initiated travel to <mapname>")
extraneous features:
add expansion pack entities
emotes
player sound effect option
players shoot through eachother (teamplay 4?)
@ -37,3 +37,4 @@ lives counting
no friendly fire
rename all functions to be lower_underscore
restart map after 10 seconds when everyone is dead
users can cancel map ends ("<name> initiated travel to <mapname>")

View File

@ -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 \