From a365e00b2278caf3675dfefa2f3ad36c59b9d1e4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Nov 2003 04:58:19 +0000 Subject: [PATCH] lemme see... fixes: stuck shamblers, cheat teslas, camming and sensing give mirvs the right death message, make them a little weaker and more spread out increased damage done by exp body... fixes not being able to use airfist if you have daedalus or lg with no cells made it so missing judo = you can't fire for 1.5 seconds, also judo doesn't always work, less chance of it working a) if they're facing you b) if they have knife, judo, or close combat you lose speed the more armor you have (so upgraded people can buy cougar and cheetah now) attempted to fix the respawn guard not telefragging bug (if it was still there) made it so you can tell a shambler to come, stop, or patrol even if it is fighting someone, doesn't really work most of the time but can "wake up" your shambler if it's being screwy (works for all demons) made it so a monster goes back to what it was doing before (following you, patrolling etc) once it's done with its enemy made the sniper rifle less cheap (or tried to), charging now = more accuracy, rather than more damage. OTR now does slightly less damage than regular, but isn't blocked by armor as much. autorifle now has half the rate of fire but does same damage as sniper rifle, but less accurate headshots always ignore armor if target has green armor, legshots always ignore armor except for red added bshams and shambler kings (can be disabled with infokeys) increased max knife blood to 32 made it so airfist bounces gymnasts twice as much, and bounces everyone a little more (I think), may cause stuck bugs but I think it won't. airfist does half damage to gymnasts and slightly more to hwguys made shamblers a little smarter and more powerful in general they now attack buildings (only bshams/kings) if they are attacked by them first bsham/king fireball now sets things on fire shamblers will generally attack the person who last hit them shortened judoka range (they have the old range if they get close combat shamblers will cycle the left-right slash or fireball longer than they did (but they won't keep doing it if their enemy is not visible) fixed shambler fireball so it doesn't miss and hurt itself so much #define OLD_AUTORIFLE will go to the old behavior of the auto rifle I think that's it oh, I changed the intro message and version string a little, you might want to change that --- ai.qc | 23 ++- airfist.qc | 34 ++++- combat.qc | 37 ++--- demoman.qc | 16 +- demon.qc | 2 +- jobs.qc | 47 ++++-- jobs.qh | 6 +- menu.qc | 3 +- messages.qh | 4 +- monsters.qc | 3 + obituary.qc | 43 +++++- ofndefs.qh | 10 +- often.qc | 9 +- options.qh | 2 +- sbitems.qc | 27 +--- security.qc | 31 ++-- shambler.qc | 430 ++++++++++++++++++++++++++++++++++++++++++---------- sniper.qc | 12 ++ tfort.qc | 7 + triggers.qc | 9 +- warlock.qc | 190 +++++++++++------------ weapons.qc | 124 +++++++++++---- wizard.qc | 2 +- 23 files changed, 738 insertions(+), 333 deletions(-) diff --git a/ai.qc b/ai.qc index e39092b..6059312 100644 --- a/ai.qc +++ b/ai.qc @@ -80,6 +80,20 @@ float(float v) anglemod = }; void(entity test) AI_Check_Contents = { + if (test.solid != SOLID_SLIDEBOX) + { + bprint(PRINT_HIGH, "CRAZY! AI_Check_Contents, test.solid="); + bprint(PRINT_HIGH, ftos(test.solid)); + bprint(PRINT_HIGH, "\n"); + } + if (test.movetype != MOVETYPE_TOSS && test.movetype != MOVETYPE_STEP) + { + bprint(PRINT_HIGH, "CRAZY! AI_Check_Contents, test.movetype="); + bprint(PRINT_HIGH, ftos(test.movetype)); + bprint(PRINT_HIGH, "\n"); + } + + //CH demons (and other ai) can be hurt by liquids //- OfN completely changed! if (pointcontents(test.origin) == CONTENTS_EMPTY && IsMonsterNonArmy(self) && self.health < self.max_health) { // Heal it @@ -105,6 +119,11 @@ void(entity test) AI_Check_Contents = rate = FIEND_REGRATE; } + if (self.is_malfunctioning) + { + heal = 0; + } + self.dmgtime = time + rate; self.health = self.health + heal;//self.has_tesla - 2; @@ -1186,6 +1205,8 @@ void(float dist) ai_run = { enemy_vis=FALSE; + self.enemy = NIL; // FindTarget ignores self.enemy, duh (fixes stuck monsters) + if (self.movetarget) self.th_walk (); else @@ -1231,7 +1252,7 @@ void(float dist) ai_run = ai_run_melee (); return; } - if (self.attack_state == AS_FIREBALL && self.classname == "monster_demon1") //CH only for demons.. + if (self.attack_state == AS_FIREBALL) //CH only for demons.. GR why? { //RPrint ("ai_run_fire\n"); ai_run_fire (); diff --git a/airfist.qc b/airfist.qc index fa25ab3..f14d40e 100644 --- a/airfist.qc +++ b/airfist.qc @@ -42,17 +42,18 @@ $frame ablast1 ablast2 ablast3 ablast4 ablast5 ablast6 float (entity thing) canairpush = { - if (thing.classname == "player") + if (thing.classname == "player") { return TRUE; + } else if (thing.classname == "pipebomb") - { + { thing.avelocity = '300 300 300'; return TRUE; - } + } else if (thing.classname == "spike") return TRUE; else if (thing.classname == "grenade") - { + { thing.avelocity = '300 300 300'; return TRUE; } @@ -102,6 +103,7 @@ void() launch_horn = { // Local variables used in the function local entity e; + local entity oself; local vector delta; local vector dir; local float eSpeed; @@ -110,6 +112,7 @@ void() launch_horn = local float ldmg; local float nearAWall; + // Constants used in the control of how the AirFist is works // Maximum strength of the AirFist. The strength of the affected entity's @@ -280,7 +283,15 @@ void() launch_horn = // take affect. // raise the bugger a bit - //setorigin(e, e.origin + '0 0 1'); // - OfN - And make them stuck in wall? :) nope.. + setorigin(e, e.origin + '0 0 1'); // - OfN - And make them stuck in wall? :) nope.. + + oself = self; + self = e; + + if (pointcontents(e.origin) == CONTENTS_SOLID) + setorigin(e, e.origin - '0 0 1'); + + self = oself; // We biased the up direction when entity is on the ground. // Looks cooler and small entitys (heath, etc) go somewhere instead @@ -298,6 +309,8 @@ void() launch_horn = if (e.classname == "player" && e.cutf_items & CUTF_HWGUY) delta = '0 0 0'; + if (e.classname == "player" && e.cutf_items & CUTF_GYMNAST) + delta *= 2; // calculate the velocity adjustment. delta = normalize(delta); @@ -343,6 +356,13 @@ void() launch_horn = // calculate the damage amount ldmg = percent * inDamage; + if (e.classname == "player") { + if (e.cutf_items & CUTF_HWGUY) // hwguy can't get knocked, but it hurts more + ldmg *= 1.5; + if (e.cutf_items & CUTF_GYMNAST) // gymnast goes with the flow, less damage + ldmg *= 0.3; + } + // This section of code is to even of the "figure momentum add" in the // T_Damage function that recoils damaged entity's away from the attacker. // NOTE: If that section of code in T_Damage changesm then this will have to @@ -404,8 +424,10 @@ void() launch_horn = // take affect. // raise the bugger a bit - //setorigin(self, self.origin + '0 0 1'); // - OfN - And make them stuck in wall? :) nope.. + setorigin(self, self.origin + '0 0 1'); // - OfN - And make them stuck in wall? - GR No, but that screws it up self.flags = self.flags - FL_ONGROUND; + if (pointcontents(self.origin) == CONTENTS_SOLID) + setorigin(self, self.origin + '0 0 -1'); } if(nearAWall) diff --git a/combat.qc b/combat.qc index 6eb0eb3..d7a98a9 100644 --- a/combat.qc +++ b/combat.qc @@ -301,10 +301,6 @@ void(entity targ, entity inflictor, entity attacker, float damage, float T_flags local string output; local float knockem; - //WK -- For LPB calculation - local string foo; - local float ping; - mirror = 0; if (infokey(NIL,"ceasefire")=="on") //Cyto return; @@ -420,11 +416,14 @@ void(entity targ, entity inflictor, entity attacker, float damage, float T_flags //DAMAGE ADJUSTMENT //- OfN - if (deathmsg != DMSG_MARTYR && targ.classname != "monster_demon1" && targ.classname != "monster_shambler" && targ.classname != "monster_army") + if (deathmsg != DMSG_MARTYR && !IsMonster(targ)) { if (targ.tfstate & TFSTATE_INSPIRED) //Chaplan defense damage = damage * 0.66; //WK Ping fairness code. LPB is < 200 ping + //haha, yeah right. +#if 0 if (attacker.classname == "player" && targ.classname == "player" && attacker != targ) { foo = infokey(attacker,"ping"); @@ -436,6 +435,7 @@ void(entity targ, entity inflictor, entity attacker, float damage, float T_flags if (ping > 1.2) ping = 1.2; damage = damage * ping; } +#endif if (teamplay & (TEAMPLAY_LESSSCOREHELP | TEAMPLAY_LESSPLAYERSHELP)) damage = TeamEqualiseDamage(targ, attacker, damage); } @@ -500,43 +500,30 @@ void(entity targ, entity inflictor, entity attacker, float damage, float T_flags // SPECIAL ARMOR CALCULATIONS if ((targ.armorclass != 0) && (T_AttackType != 0)) { + // OTR changed, it now just does less damage but ignores armor. if ((targ.armorclass & AT_SAVESHOT) && (T_AttackType == TF_TD_SHOT)) { damage = floor(damage * 0.5); //WK Cap max damage you can take with kevlar on, like in Real Life(tm) //WK The purpose being to cut down on the power of snipers if(targ.classname == "player") // SB kevlar fixed so it caps damage now, also spacing much nicer :) { - local float olddamage; //- OfN - special cap damage with otr! heh - olddamage=damage; - if (light_damage) + if (light_damage) { if (damage > 75) damage = 75; } - else - if (damage > 100) damage = 100; + else if (damage > 100) damage = 100; - if (attacker.classname == "player" && (deathmsg == DMSG_SNIPERRIFLE || deathmsg == DMSG_SNIPERHEADSHOT || deathmsg == DMSG_SNIPERLEGSHOT)) - { - sprint(attacker,PRINT_HIGH,"You hit kevlar\n"); - if (attacker.cutf_items & CUTF_OTR) //- OfN - - { - if (olddamage > 100) - olddamage=olddamage - ((olddamage - 100)*0.4); - - damage = olddamage; - } - - } } } else if ((targ.armorclass & AT_SAVEMELEE) && (deathmsg == DMSG_JUDOKA || deathmsg == DMSG_AXE || deathmsg == DMSG_BACKSTAB || deathmsg == DMSG_SPANNER)) { + // This crap should all be in the weapon function. Stupid morons. damage = floor(damage * 0.5); if ((targ.velocity_x > 0 || targ.velocity_y > 0 || targ.velocity_z > 0) && random() > 0.6) return; - if (deathmsg == DMSG_BACKSTAB) + if (deathmsg == DMSG_BACKSTAB) // O_O, why is this here? T_flags = T_flags - (T_flags & TF_TD_IGNOREARMOUR); } else if ((targ.armorclass & AT_SAVEEXPLOSION) && (T_AttackType == TF_TD_EXPLOSION)) @@ -563,6 +550,7 @@ void(entity targ, entity inflictor, entity attacker, float damage, float T_flags targ.armortype = 0; // lost all armor targ.armorclass = 0; // lost special armor targ.items = targ.items & ~(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3); + TeamFortress_SetSpeed(targ); } //WK Flags prevent armor damage too if (T_flags & TF_TD_NOTTEAM) @@ -595,6 +583,8 @@ void(entity targ, entity inflictor, entity attacker, float damage, float T_flags } // targ.armorvalue = targ.armorvalue - save; take = ceil(damage-save); + if (targ.armorvalue > 0 && (targ.armorvalue + save > 100)) + TeamFortress_SetSpeed(targ); // speed up the less armor you have } // add to the damage total for clients, which will be sent as a single // message at the end of the frame @@ -743,9 +733,6 @@ void(entity targ, entity inflictor, entity attacker, float damage, float T_flags if (self.th_pain) { self.th_pain (attacker, take); - // nightmare mode monsters don't go into pain frames often - if (skill >= 3) - self.pain_finished = time + 5; } self = oldself; diff --git a/demoman.qc b/demoman.qc index f3b1f4f..3a98b8f 100644 --- a/demoman.qc +++ b/demoman.qc @@ -106,8 +106,8 @@ void (vector org, entity shooter) MirvGrenadeLaunch = local float xdir,ydir,zdir; xdir = 150 * random() - 75; - ydir = 150 * random() - 75; - zdir = 40 * random(); + ydir = 2 * (100 - fabs(xdir)) * random() - (75 - fabs(xdir)); + zdir = 170 - (fabs(xdir) + fabs(ydir)); newmis = spawn (); newmis.owner = shooter; @@ -118,8 +118,8 @@ void (vector org, entity shooter) MirvGrenadeLaunch = newmis.weapon = DMSG_GREN_MIRV; #ifdef NET_SERVER - newmis.touch = NormalGrenadeTouch; - newmis.think = NormalGrenadeExplode; + newmis.touch = GrenadeTouch; + newmis.think = GrenadeExplode; #else newmis.touch = GrenadeTouch; newmis.think = GrenadeExplode; @@ -128,11 +128,11 @@ void (vector org, entity shooter) MirvGrenadeLaunch = //WK 2 + random newmis.nextthink = time + 0.75 + random(); - newmis.velocity_x = xdir * 2; - newmis.velocity_y = ydir * 2; - newmis.velocity_z = zdir * 15; + newmis.velocity_x = xdir * 3; + newmis.velocity_y = ydir * 3; + newmis.velocity_z = zdir * 5; - newmis.avelocity='100 100 400'; + newmis.avelocity='100 100 500'; setmodel (newmis, "progs/grenade2.mdl"); setsize (newmis, VEC_ORIGIN, VEC_ORIGIN); diff --git a/demon.qc b/demon.qc index 3bc7d93..d82ecaa 100644 --- a/demon.qc +++ b/demon.qc @@ -708,7 +708,7 @@ void() monster_demon_respawn = void () custom_demon_die = { - if (self.real_owner.classname == "player") + if (self.real_owner.classname == "player" && self.real_owner.demon_one == self) { sprint(self.real_owner,PRINT_HIGH,"Your fiend is dead.\n"); self.real_owner.job = self.real_owner.job - (self.real_owner.job & JOB_DEMON_OUT); diff --git a/jobs.qc b/jobs.qc index c7a0db8..1f71d0c 100644 --- a/jobs.qc +++ b/jobs.qc @@ -13,6 +13,7 @@ Functions for handling the custom class professions //WK - all of this +void(float delay) Attack_Finished; void() DropToCustomClassGen; //Called when starting class generation void() DropFromCustomClassGen; //Called when finished class generation void() PrintMoney; @@ -490,10 +491,6 @@ void() JobBerserker = //So we don't have to do error checking on those situations //Four special cases, Rifle, Medikit, AC and Grapple, have side effects // when you remove them. Need special cases to handle their theft -#define DISARM_TIME 10 -#define CANT_ATTACK_TIME 5 -#define HIT_DELAY 8 -#define MISS_DELAY 1 void() JudokaRearm = { //Self.owner is the guy who had his weapon taken away @@ -574,22 +571,48 @@ void() JobJudoka = //Take the weapon of any person in front of you and force a reload self.job_finished = time + MISS_DELAY; //Delay if we don't hit local vector source; + local vector dir; + local float chance; local entity tWeapon,oself; local entity te; makevectors(self.v_angle); source = self.origin + '0 0 16'; - traceline (source, source + v_forward*96, FALSE, self); - if (trace_fraction == 1.0) { - sprint (self, PRINT_HIGH, "You miss.\n"); - return; - } - if (trace_ent.classname == "player" && !Teammate(trace_ent.team_no, self.team_no) && trace_ent.playerclass != PC_UNDEFINED) + if (self.cutf_items & CUTF_CLOSECOMBAT) + traceline(source, source + v_forward*96, FALSE, self); + else + traceline(source, source + v_forward*64, FALSE, self); + + if (trace_fraction != 1.0 && trace_ent.classname == "player" && !Teammate(trace_ent.team_no, self.team_no) && trace_ent.playerclass != PC_UNDEFINED) { if (self.is_undercover) //Taking someone's weapon should give you away Spy_RemoveDisguise(self); + // Let's not make it work all the time + dir = normalize (trace_ent.origin - self.origin); + makevectors(trace_ent.v_angle); + + chance = dir * normalize(v_forward); + chance *= 0.35; + if (chance > 0.25) + chance = 0.25; + if (trace_ent.job & JOB_JUDOKA) + chance += 0.2; + if (trace_ent.cutf_items & CUTF_CLOSECOMBAT) + chance += 0.25; + if (trace_ent.current_weapon == WEAP_AXE && trace_ent.cutf_items & CUTF_KNIFE) + chance += 0.1; + if (self.cutf_items & CUTF_CLOSECOMBAT) + chance -= 0.25; + + if (random() > chance) + { + sprint (self, PRINT_HIGH, "Your strike is parried!\n"); + Attack_Finished(3); + return; + } + sprint (trace_ent, PRINT_HIGH, "You have been disarmed by "); sprint (trace_ent, PRINT_HIGH, self.netname); sprint (trace_ent, PRINT_HIGH, "\n"); @@ -690,9 +713,13 @@ void() JobJudoka = } self.job_finished = time + HIT_DELAY; + Attack_Finished(0.5); } else + { sprint (self, PRINT_HIGH, "You miss.\n"); + Attack_Finished(1.5); + } }; diff --git a/jobs.qh b/jobs.qh index e38a6b5..b49cf91 100644 --- a/jobs.qh +++ b/jobs.qh @@ -45,10 +45,10 @@ Functions for handling the custom class professions //So we don't have to do error checking on those situations //Four special cases, Rifle, Medikit, AC and Grapple, have side effects // when you remove them. Need special cases to handle their theft -#define DISARM_TIME 10 -#define CANT_ATTACK_TIME 5 +#define DISARM_TIME 20 +#define CANT_ATTACK_TIME 3 #define HIT_DELAY 8 -#define MISS_DELAY 1 +#define MISS_DELAY 3 /* ** Guerilla Profession - diff --git a/menu.qc b/menu.qc index 5371ea1..73268ed 100644 --- a/menu.qc +++ b/menu.qc @@ -2402,7 +2402,6 @@ void(float inp) Menu_EngineerFix_Tesla_Input2 = sprint(self, PRINT_HIGH, "Gun is already deployed\n"); } else { - self.building.origin_z = self.building.origin_z + 15; // +15//Elevate for the check //Make sure the launch area is clear if (FALSE) { //if (CheckArea(self.building,self) == FALSE) { @@ -2411,7 +2410,7 @@ void(float inp) Menu_EngineerFix_Tesla_Input2 = } else { //self.building.origin_z = self.building.origin_z + 25; //+ 25 //Finish liftoff - self.building.origin_z = self.building.origin_z - 25; //often fixes tesla not touchin ceiling//+ 25 //Finish liftoff + self.building.origin_z = self.building.origin_z - 34; //often fixes tesla not touchin ceiling//+ sprint(self, PRINT_HIGH, "You turretize the tesla\n"); if (self.building.job == 1 && self.building.tf_items & NIT_TESLA_CLOAKING) diff --git a/messages.qh b/messages.qh index 0a09cdc..623cb58 100644 --- a/messages.qh +++ b/messages.qh @@ -1,11 +1,11 @@ // This file contains defines for some of the messages #define MSG_INTRO1 "Welcome to 幸馅撩 Custom云\na Quake 云 MOD by ShakaUVM\nwww畉elefragged甤om痵haka" -#define MSG_INTRO2 "Based on the aussie ver by SB-1\nModified version by Clan Prozac" +#define MSG_INTRO2 "Hacked by KK, then SB-1 then OfN, then the Quakeforge team, then Grievre" //#define MSG_INTRO3 "Get any files needed at:\n\nhttp:\^/\^/quake\^.prozac\^.net\^/" #define MSG_INTROBAR "\n\n潪灋灋灋灋灋灋灋灋灋灋灋灋灍\n\n" //, aka 驝敀拻 //#define MSG_CUTFVERSION "Custom云 version 32甇fN" -#define MSG_CUTFVERSION "幸馅撩 Custom云 32甇fN4" +#define MSG_CUTFVERSION "幸馅撩 Custom云 32甇fN4-qfcc-GR3" // Comments CenterPrinted when a player gets the CTF flag #define MSG_CTF_FLAG_GRAB_TEAM1 "You got the enemy flag!\n\nFlee!" diff --git a/monsters.qc b/monsters.qc index 1a5f569..ca1afd0 100644 --- a/monsters.qc +++ b/monsters.qc @@ -533,6 +533,9 @@ void() walkmonster_start_go = // local float failure; // local vector test; + self.movetype = MOVETYPE_STEP; + self.solid = SOLID_SLIDEBOX; + self.origin_z = self.origin_z + 1; // raise off floor a bit droptofloor(); diff --git a/obituary.qc b/obituary.qc index 5c8f17f..ffdcf6f 100644 --- a/obituary.qc +++ b/obituary.qc @@ -431,9 +431,10 @@ void (entity targ, entity attacker) Obituary_Player_by_Shambler = { custom_demon_name (attacker); //CH - if (attacker.real_owner == targ) { - Give_Frags_Out (attacker.real_owner, attacker.real_owner, -2, 0, 1, 1, 0); - + if (attacker.real_owner == targ || (attacker.is_malfunctioning && attacker.martyr_enemy == targ)) { + + if (!attacker.is_malfunctioning) + Give_Frags_Out (attacker.real_owner, attacker.real_owner, -2, 0, 1, 1, 0); if (deathmsg == DMSG_LIGHTNING) { bprint (PRINT_MEDIUM, attacker.netname); bprint (PRINT_MEDIUM, " annihilates its owner "); @@ -444,6 +445,14 @@ void (entity targ, entity attacker) Obituary_Player_by_Shambler = bprint (PRINT_MEDIUM, " detonates its owner "); bprint (PRINT_MEDIUM, targ.netname); bprint (PRINT_MEDIUM, " with a fireball\n"); + } else if (deathmsg == DMSG_FLAME && attacker.has_tesla > 5) { + bprint (PRINT_MEDIUM, targ.netname); + if (attacker.has_tesla == 6) + bprint (PRINT_MEDIUM, " was torched by his own battle shambler, "); + else + bprint (PRINT_MEDIUM, " was deep-fried by his ally, "); + bprint (PRINT_MEDIUM, attacker.netname); + bprint (PRINT_MEDIUM, "\n"); } else { if (random () < FRAC (1, 2)) { bprint (PRINT_MEDIUM, attacker.netname); @@ -483,12 +492,24 @@ void (entity targ, entity attacker) Obituary_Player_by_Shambler = bprint (PRINT_MEDIUM, ") lightning\n"); } else { bprint (PRINT_MEDIUM, attacker.real_owner.netname); - bprint (PRINT_MEDIUM, "'s shambler, "); + if (attacker.has_tesla < 6) + bprint (PRINT_MEDIUM, "'s shambler, "); + else if (attacker.has_tesla == 6) + bprint (PRINT_MEDIUM, "'s battle shambler, "); + else + bprint (PRINT_MEDIUM, "'s shambler king, "); bprint (PRINT_MEDIUM, attacker.netname); bprint (PRINT_MEDIUM, ", teaches "); bprint (PRINT_MEDIUM, targ.netname); bprint (PRINT_MEDIUM, " to cook without gas\n"); } + } else if (deathmsg == DMSG_FLAME) { + bprint (PRINT_MEDIUM, targ.netname); + bprint (PRINT_MEDIUM, " is immolated by "); + bprint (PRINT_MEDIUM, attacker.netname); + bprint (PRINT_MEDIUM, " ("); + bprint (PRINT_MEDIUM, attacker.real_owner.netname); + bprint (PRINT_MEDIUM, ")'s hellfire\n"); } else if (deathmsg == DMSG_DEMON_FIRE) { if (random () < FRAC (1, 2)) { bprint (PRINT_MEDIUM, targ.netname); @@ -2165,13 +2186,19 @@ void (entity targ, entity attacker) Obituary_Monster_Shambler_by_Shambler = { custom_demon_name (attacker); - if (Teammate (targ.real_owner.team_no, attacker.real_owner.team_no)) { + if (attacker == targ && deathmsg == DMSG_FLAME) + { + bprint (PRINT_MEDIUM, attacker.netname); + bprint (PRINT_MEDIUM, " ("); + bprint (PRINT_MEDIUM, attacker.real_owner.netname); + bprint (PRINT_MEDIUM, ") sets itself on fire one too many times.\n"); + } else if (Teammate (targ.real_owner.team_no, attacker.real_owner.team_no)) { Give_Frags_Out (attacker, targ, -1, 0, 1, 1, 0); bprint (PRINT_MEDIUM, attacker.netname); bprint (PRINT_MEDIUM, " ("); bprint (PRINT_MEDIUM, attacker.real_owner.netname); - bprint (PRINT_MEDIUM, ") electrifies the friendly shambler "); + bprint (PRINT_MEDIUM, ") destroys the friendly shambler "); bprint (PRINT_MEDIUM, targ.netname); bprint (PRINT_MEDIUM, " ("); bprint (PRINT_MEDIUM, targ.real_owner.netname); @@ -2234,7 +2261,7 @@ void (entity targ, entity attacker) Obituary_Monster_Shambler_by_Wizard = bprint (PRINT_MEDIUM, attacker.netname); bprint (PRINT_MEDIUM, " ("); bprint (PRINT_MEDIUM, attacker.real_owner.netname); - bprint (PRINT_MEDIUM, ") kills the friendly soldier "); + bprint (PRINT_MEDIUM, ") nullifies the friendly shambler "); bprint (PRINT_MEDIUM, targ.netname); bprint (PRINT_MEDIUM, " ("); bprint (PRINT_MEDIUM, targ.real_owner.netname); @@ -2245,7 +2272,7 @@ void (entity targ, entity attacker) Obituary_Monster_Shambler_by_Wizard = bprint (PRINT_MEDIUM, targ.netname); bprint (PRINT_MEDIUM, " ("); bprint (PRINT_MEDIUM, targ.real_owner.netname); - bprint (PRINT_MEDIUM, ") had his army career truncated by the scrag "); + bprint (PRINT_MEDIUM, ") is destroyed by the scrag "); //bprint (PRINT_MEDIUM, attacker.undercover_name); bprint (PRINT_MEDIUM, attacker.netname); bprint (PRINT_MEDIUM, " ("); diff --git a/ofndefs.qh b/ofndefs.qh index d6ce6e5..f0165ab 100644 --- a/ofndefs.qh +++ b/ofndefs.qh @@ -23,10 +23,10 @@ #define MOTD_REFRESHRATE 1 -#define MAX_KNIFE_BLOOD 12 // maximum of knife kill points that can be accumulated by warlocks +#define MAX_KNIFE_BLOOD 32 // maximum of knife kill points that can be accumulated by warlocks #define GRUNTY_HP 600 // initial HP for soldier -#define GRUNT_MAX_HP 1200 // OfN - Max health for the damn soldier, no 5000 hp grunts anymore! =) +#define GRUNT_MAX_HP 2000 // OfN - Max health for the damn soldier, no 5000 hp grunts anymore! =) GR - why not? #define SHAMBLER_HP 2600 // 2000 - 3000 - 2600 #define HKNIGHT_HP 2200 // @@ -37,14 +37,16 @@ #define SCRAG_DMG 29 // damage the scrag does #define WAYPOINT_LIFE 240 // 120 after this amount of seconds any unused waypoint will be removed -#define OTR_DMGFACTOR 1.10 // *damage facter for the OTR armed sniper rifle (MUST BE GREATER THAN 1!!!) +#define OTR_DMGFACTOR 0.6 // *damage facter for the OTR armed sniper rifle (MUST BE GREATER THAN 1!!!) no #define SENTRY_UNLOCKTIME 2.5 // (must be greater than 1.1) time for the sentries to begin to rotate after they have no target (+/- 1 second) #define HAX_UNSTABLEDIST 300 // distance at which enemy hacks take longer cause of "unstable connection" #define WAYPOINT_AI_LIFE 10 // life for grunty ai created waypoints - last seen enemy mark #define ATTN_MONSTERDIE ATTN_NONE // ATTN_NORM #define MINE_SCANRATE 0.6 // mines look again for nearby enemy after this time - it was 1 which caused high ping players to not trigger mines sometimes walking around them fast -#define EXPBODY_DMG 160 // damage exp. body does /was 140 +#define EXPBODY_DMG 200 // damage exp. body does /was 140 GR this was really really wimpy #define MINE_DMG 200 // was 240 /215 +#define SNIPER_DMG 90 // was charge up. Makes more sense for sniper bullets to do constant damage. +#define OTR_DMG 50 // extra damage done by OTR (always ignores armor) #define BERSERKER_HP_COST 30 diff --git a/often.qc b/often.qc index 66ea86b..e8d0abc 100644 --- a/often.qc +++ b/often.qc @@ -685,7 +685,14 @@ string(entity themonster) GetMonsterName = if (themonster.classname == "monster_wizard") return "scrag"; if (themonster.classname == "monster_shambler") - return "shambler"; + { + if (themonster.has_tesla > 6) + return "shambler king"; + if (themonster.has_tesla == 6) + return "battle shambler"; + else + return "shambler"; + } if (themonster.classname == "monster_demon1") return "fiend"; if (themonster.classname == "monster_army") diff --git a/options.qh b/options.qh index c729040..5b859a3 100644 --- a/options.qh +++ b/options.qh @@ -36,7 +36,7 @@ Defines for the compilable options within TF. #define FLAME_MAXWORLDNUM 60 // maximum number of flames in the world. DO NOT PUT BELOW 20. #define MAX_WORLD_PIPEBOMBS 30 // This is divided between teams #define MAX_WORLD_AMMOBOXES 6 // This is divided between teams - #define GR_TYPE_MIRV_NO 12 // Number of Mirvs a Mirv Grenade breaks into + #define GR_TYPE_MIRV_NO 4 // Number of Mirvs a Mirv Grenade breaks into #define GR_TYPE_NAPALM_NO 12 // Number of flames napalm grenade breaks into #endif diff --git a/sbitems.qc b/sbitems.qc index b603843..c6ed00e 100644 --- a/sbitems.qc +++ b/sbitems.qc @@ -320,26 +320,7 @@ void() MotionSensorTossTouch = { if (other || other == self.real_owner) return; - if (pointcontents(self.origin) == CONTENTS_SKY || pointcontents(self.origin + '0 0 2') == CONTENTS_SKY || pointcontents(self.origin) == CONTENTS_SOLID) - { - MotionSensorDie(); - return; - } - //CH sees where landed and adjusts to proper things - if (pointcontents(self.origin + '0 0 1') == CONTENTS_SOLID) - self.origin = self.origin - '0 0 12'; - if (pointcontents(self.origin - '0 0 1') == CONTENTS_SOLID) - self.origin = self.origin + '0 0 4'; - if (pointcontents(self.origin + '0 1 0') == CONTENTS_SOLID) - self.origin = self.origin - '0 16 0'; - if (pointcontents(self.origin - '0 1 0') == CONTENTS_SOLID) - self.origin = self.origin + '0 16 0'; - if (pointcontents(self.origin + '1 0 0') == CONTENTS_SOLID) - self.origin = self.origin - '16 0 0'; - if (pointcontents(self.origin + '1 0 0') == CONTENTS_SOLID) - self.origin = self.origin + '16 0 0'; - setorigin (self, self.origin); - if (pointcontents(self.origin) == CONTENTS_SKY || pointcontents(self.origin + '0 0 2') == CONTENTS_SKY || pointcontents(self.origin) == CONTENTS_SOLID) + if (pointcontents(self.origin) == CONTENTS_SKY || pointcontents(self.origin + '0 0 18') == CONTENTS_SKY || pointcontents(self.origin) == CONTENTS_SOLID) { MotionSensorDie(); return; @@ -485,18 +466,20 @@ void() MotionSensorSpawn = self.has_sensor = TRUE; newmis = spawn(); newmis.movetype = MOVETYPE_BOUNCE; - setsize (newmis, '0 0 0', '0 0 0'); + setsize (newmis, '-16 -16 -6', '16 16 10'); // setsize (newmis, '-8 -8 -8', '8 8 8'); newmis.solid = SOLID_BBOX; newmis.takedamage = DAMAGE_AIM; newmis.classname = "building_sensor"; newmis.netname = "motion_sensor"; - setorigin (newmis, self.origin); + newmis.origin = self.origin; newmis.owner = NIL; newmis.real_owner = self; makevectors (self.v_angle); newmis.avelocity = '0 0 0'; newmis.velocity = v_forward*800 + v_up * 200 + v_right*10 + v_up*10; + newmis.origin += normalize(newmis.velocity) * 20; + setorigin(newmis, newmis.origin); newmis.angles = '0 0 0'; newmis.angles_y = anglemod(self.angles_y + 180); // newmis.skin = 1; diff --git a/security.qc b/security.qc index abd02a5..a16744b 100644 --- a/security.qc +++ b/security.qc @@ -227,18 +227,20 @@ void() Security_Camera_Spawn = self.has_camera = TRUE; newmis = spawn(); newmis.movetype = MOVETYPE_BOUNCE; - setsize (newmis, '0 0 0', '0 0 0'); + setsize (newmis, '-16 -16 -6', '16 16 10'); // setsize (newmis, '-8 -8 -8', '8 8 8'); newmis.solid = SOLID_BBOX; newmis.takedamage = DAMAGE_AIM; newmis.classname = "building_camera"; newmis.netname = "security_camera"; - setorigin (newmis, self.origin); + newmis.origin = self.origin; newmis.owner = NIL; newmis.real_owner = self; makevectors (self.v_angle); newmis.avelocity = '0 0 0'; newmis.velocity = v_forward*800 + v_up * 200 + v_right*10 + v_up*10; + newmis.origin += (normalize(newmis.velocity) * 20); + setorigin(newmis, newmis.origin); newmis.angles = '0 0 0'; newmis.angles_y = anglemod(self.angles_y + 180); // newmis.skin = 1; @@ -250,6 +252,9 @@ void() Security_Camera_Spawn = newmis.colormap = self.colormap; newmis.heat = 0; //Beeps + newmis.think = Security_Camera_Die; + newmis.nextthink = time + 5; + newmis.health = newmis.max_health = BUILD_HEALTH_CAMERA; newmis.touch = SecurityCameraTossTouch; @@ -263,30 +268,12 @@ void() SecurityCameraTossTouch = { if (other || other == self.real_owner) return; - if (pointcontents(self.origin) == CONTENTS_SKY || pointcontents(self.origin + '0 0 2') == CONTENTS_SKY || pointcontents(self.origin) == CONTENTS_SOLID) - { - Security_Camera_Die(); - return; - } - //CH sees where landed and adjusts to proper things - if (pointcontents(self.origin + '0 0 1') == CONTENTS_SOLID) - self.origin = self.origin - '0 0 12'; - if (pointcontents(self.origin - '0 0 1') == CONTENTS_SOLID) - self.origin = self.origin + '0 0 4'; - if (pointcontents(self.origin + '0 1 0') == CONTENTS_SOLID) - self.origin = self.origin - '0 16 0'; - if (pointcontents(self.origin - '0 1 0') == CONTENTS_SOLID) - self.origin = self.origin + '0 16 0'; - if (pointcontents(self.origin + '1 0 0') == CONTENTS_SOLID) - self.origin = self.origin - '16 0 0'; - if (pointcontents(self.origin + '1 0 0') == CONTENTS_SOLID) - self.origin = self.origin + '16 0 0'; - setorigin (self, self.origin); - if (pointcontents(self.origin) == CONTENTS_SKY || pointcontents(self.origin + '0 0 2') == CONTENTS_SKY || pointcontents(self.origin) == CONTENTS_SOLID) + if (pointcontents(self.origin) == CONTENTS_SKY || pointcontents(self.origin + '0 0 12') == CONTENTS_SKY || pointcontents(self.origin) == CONTENTS_SOLID) { Security_Camera_Die(); return; } + sprint (self.real_owner, PRINT_HIGH, "You finish building the Security Camera.\n"); teamprefixsprint(self.real_owner.team_no,self.real_owner); //- OfN diff --git a/shambler.qc b/shambler.qc index 831b06b..6906875 100644 --- a/shambler.qc +++ b/shambler.qc @@ -1,9 +1,12 @@ #include "defs.qh" -//void(float side) ShamFireball; -//void() sham_fireballl1; -//void() sham_fireballr1; -//void() shambler_fire_touch; +void(float side) ShamFireball; +void() sham_fireballl1; +void() sham_fireballr1; +void() shambler_fire_touch; +void() shambler_fire_think; float (entity targ, entity inflictor) CanDamage; + +void() Napalm_touch; /* ============================================================================== @@ -61,27 +64,31 @@ void() sham_stand15 =[ $stand15, sham_stand16] {ai_stand();}; void() sham_stand16 =[ $stand16, sham_stand17] {ai_stand();}; void() sham_stand17 =[ $stand17, sham_stand1 ] {ai_stand();}; -void() sham_walk1 =[ $walk1, sham_walk2 ] {ai_walk(10);}; -void() sham_walk2 =[ $walk2, sham_walk3 ] {ai_walk(9);}; -void() sham_walk3 =[ $walk3, sham_walk4 ] {ai_walk(9);}; -void() sham_walk4 =[ $walk4, sham_walk5 ] {ai_walk(5);}; -void() sham_walk5 =[ $walk5, sham_walk6 ] {ai_walk(6);}; -void() sham_walk6 =[ $walk6, sham_walk7 ] {ai_walk(12);}; -void() sham_walk7 =[ $walk7, sham_walk8 ] {ai_walk(8);}; -void() sham_walk8 =[ $walk8, sham_walk9 ] {ai_walk(3);}; -void() sham_walk9 =[ $walk9, sham_walk10] {ai_walk(13);}; -void() sham_walk10 =[ $walk10, sham_walk11] {ai_walk(9);}; -void() sham_walk11 =[ $walk11, sham_walk12] {ai_walk(7);}; -void() sham_walk12 =[ $walk12, sham_walk1 ] {ai_walk(7); +void() sham_walk1 =[ $walk1, sham_walk2 ] {ai_walk(2*(self.has_tesla));}; +void() sham_walk2 =[ $walk2, sham_walk3 ] {ai_walk(2*(self.has_tesla));}; +void() sham_walk3 =[ $walk3, sham_walk4 ] {ai_walk(2*(self.has_tesla));}; +void() sham_walk4 =[ $walk4, sham_walk5 ] {ai_walk(self.has_tesla);}; +void() sham_walk5 =[ $walk5, sham_walk6 ] {ai_walk(1.5*(self.has_tesla));}; +void() sham_walk6 =[ $walk6, sham_walk7 ] {ai_walk(5*self.has_tesla);}; +void() sham_walk7 =[ $walk7, sham_walk8 ] {ai_walk(2*(self.has_tesla));}; +void() sham_walk8 =[ $walk8, sham_walk9 ] {ai_walk(3*(self.has_tesla-4));}; +void() sham_walk9 =[ $walk9, sham_walk10] {ai_walk(6*self.has_tesla);}; +void() sham_walk10 =[ $walk10, sham_walk11] {ai_walk(3*self.has_tesla);}; +void() sham_walk11 =[ $walk11, sham_walk12] {ai_walk(1.8*(self.has_tesla));}; +void() sham_walk12 =[ $walk12, sham_walk1 ] {ai_walk(1.8*(self.has_tesla)); if (random() > 0.8) sound (self, CHAN_VOICE, "shambler/sidle.wav", 1, ATTN_IDLE);}; -void() sham_run1 =[ $run1, sham_run2 ] {ai_run(20);}; -void() sham_run2 =[ $run2, sham_run3 ] {ai_run(24);}; -void() sham_run3 =[ $run3, sham_run4 ] {ai_run(20);}; -void() sham_run4 =[ $run4, sham_run5 ] {ai_run(20);}; -void() sham_run5 =[ $run5, sham_run6 ] {ai_run(24);}; -void() sham_run6 =[ $run6, sham_run1 ] {ai_run(20); +void() sham_run = { + sham_run1(); +}; + +void() sham_run1 =[ $run1, sham_run2 ] {ai_run(5*self.has_tesla);}; +void() sham_run2 =[ $run2, sham_run3 ] {ai_run(6*self.has_tesla);}; +void() sham_run3 =[ $run3, sham_run4 ] {ai_run(5*self.has_tesla);}; +void() sham_run4 =[ $run4, sham_run5 ] {ai_run(5*self.has_tesla);}; +void() sham_run5 =[ $run5, sham_run6 ] {ai_run(6*self.has_tesla);}; +void() sham_run6 =[ $run6, sham_run1 ] {ai_run(5*self.has_tesla); if (random() > 0.8) sound (self, CHAN_VOICE, "shambler/sidle.wav", 1, ATTN_IDLE); @@ -104,15 +111,24 @@ local vector delta; local float ldmg; if (!self.enemy) + { + self.has_teleporter += 1; return; + } ai_charge(0); delta = self.enemy.origin - self.origin; if (vlen(delta) > 200) + { + self.has_teleporter += 1; return; + } if (!CanDamage (self.enemy, self)) + { + self.has_teleporter += 1; return; + } ldmg = (random() + random() + random()) * 200 + 30*self.has_tesla; deathmsg = 0; @@ -124,6 +140,7 @@ local float ldmg; SpawnMeatSpray (self.origin + v_forward*16, crandom() * 100 * v_right); SpawnMeatSpray (self.origin + v_forward*16, crandom() * 100 * v_right); + self.has_teleporter -= 1; }; void() sham_smash11 =[ $smash11, sham_smash12 ] {ai_charge(10 * (0.7 + self.has_tesla * 0.2));}; // spd dbl void() sham_smash12 =[ $smash12, sham_run1 ] {ai_charge(8 * (0.7 + self.has_tesla * 0.2));}; @@ -137,14 +154,21 @@ local float ldmg; if (!self.enemy) + { + self.has_teleporter += 1; return; + } + ai_charge(20 * (0.7 + self.has_tesla * 0.2)); //spd dbl delta = self.enemy.origin - self.origin; if (vlen(delta) > 200) + { + self.has_teleporter += 1; return; - + } + deathmsg = 0; ldmg = (random() + random() + random()) * 75 + 15*self.has_tesla; @@ -168,6 +192,7 @@ local float ldmg; SpawnMeatSpray (self.origin + v_forward*16, side * v_right); } + self.has_teleporter -= 1; }; void() sham_swingl1 =[ $swingl1, sham_swingl2 ] { @@ -201,7 +226,7 @@ self.enemy = NIL; void() sham_swingl8 =[ $swingl8, sham_swingl9 ] {ai_charge(8);}; void() sham_swingl9 =[ $swingl9, sham_run1 ] { ai_charge(16); -if (random()<0.5) +if (self.enemy && random()<0.5) self.think = sham_swingr1; }; @@ -235,7 +260,7 @@ self.enemy = NIL; }; void() sham_swingr8 =[ $swingr8, sham_swingr9 ] {ai_charge(6);}; void() sham_swingr9 =[ $swingr9, sham_run1 ] {ai_charge(2); -if ((self.has_sensor && self.enemy.health > 0 && random()<0.5) || (!self.has_sensor && self.enemy.health <= 0 && random()<0.5)) +if ((self.enemy && random()<0.5)) self.think = sham_swingl1; }; @@ -245,9 +270,9 @@ void() sham_melee = chance = random(); self.has_sensor = 1; - if (chance > 0.7) + if (chance > 0.8) sham_smash1 (); - else if (chance > 0.35) + else if (chance > 0.4) sham_swingr1 (); else sham_swingl1 (); @@ -267,7 +292,7 @@ void() CastLightning = org = self.origin + '0 0 40'; - dir = self.enemy.origin + '0 0 16' - org; + dir = (self.enemy.origin + '0 0 30') - org; dir = normalize (dir); // OfN - Check for force field @@ -289,11 +314,20 @@ void() CastLightning = WriteCoord (MSG_MULTICAST, trace_endpos_z); multicast (org, MULTICAST_PHS); - return; + + self.has_sentry += 1; + return; } + + if (!trace_ent.takedamage) + self.has_sentry += 1; + else + self.has_sentry -= 1; + + //_------------------------------------_// - traceline (org, self.origin + dir*3000, TRUE, self); + traceline (org, self.origin + dir*(3000 + self.has_tesla * 2), TRUE, self); WriteByte (MSG_MULTICAST, SVC_TEMPENTITY); WriteByte (MSG_MULTICAST, TE_LIGHTNING1); @@ -305,8 +339,8 @@ void() CastLightning = WriteCoord (MSG_MULTICAST, trace_endpos_y); WriteCoord (MSG_MULTICAST, trace_endpos_z); - ldmg = 5 + self.has_tesla * 5; - if (self.has_tesla == 5) + ldmg = self.has_tesla * 2; + if (self.has_tesla > 5) if (ldmg < self.enemy.health) self.health = self.health + (ldmg / 10); else @@ -314,7 +348,7 @@ void() CastLightning = if (self.health > self.max_health) self.health = self.max_health; - LightningDamage (org, trace_endpos, self, 5 + self.has_tesla * 5); + LightningDamage (org, trace_endpos, self, ldmg); }; @@ -357,7 +391,7 @@ void() sham_magic10 =[ $magic10, sham_magic11 ] {CastLightning();}; void() sham_magic11 =[ $magic11, sham_magic12 ] { -if (skill == 3) +if (self.has_tesla > 5) CastLightning(); }; void() sham_magic12 =[ $magic12, sham_run1 ] {self.effects = 0;}; @@ -379,13 +413,24 @@ void(entity attacker, float damage) sham_pain = //self.real_owner.StatusRefreshTime = time + 0.2; //self.real_owner.StatusBarScreen = 3; + if (attacker.takedamage && self.has_tesla > 5 && attacker != self && !(IsMonsterNonArmy(attacker) && self.real_owner == attacker.real_owner)) + { + if (self.enemy.classname != "player" || !Teammate(self.real_owner.team_no, self.enemy.team_no)) + self.oldenemy = self.enemy; + + if (attacker != self.enemy) { + self.enemy = attacker; + HuntTarget(); + } + } + if (self.pain_finished > time) return; if (self.health <= 0) return; // allready dying, don't go into pain frame - if (random()*100 > damage) // was 70 + if (random()*self.has_tesla*100 > damage) // was 70 return; // didn't flinch sound (self, CHAN_VOICE, "shambler/shurt2.wav", 1, ATTN_NORM); @@ -417,7 +462,7 @@ void() custom_shambler_die = { self.effects=0; - if (self.real_owner.classname == "player") + if (self.real_owner.classname == "player" && self.real_owner.demon_one == self) { sprint(self.real_owner,PRINT_HIGH,"Your shambler is dead.\n"); self.real_owner.job = self.real_owner.job - (self.real_owner.job & JOB_DEMON_OUT); @@ -451,21 +496,69 @@ float () CheckShamMelee = local vector dist; local float d; + + if (self.has_teleporter < -2) + self.has_teleporter = -2; + + if (self.has_teleporter > 2 && self.has_teleporter > (14 - 2*self.has_tesla)) + { + self.has_teleporter -= 0.1; + return FALSE; + } + dist = self.enemy.origin - self.origin; d = vlen(dist); if (d < 150) //CH Check reach { - self.attack_state = AS_MELEE; return TRUE; } return FALSE; }; +float () CheckShamFireball = +{ + local vector dist; + + if (self.has_tesla <= 5) + { + return FALSE; + } + + if (self.has_fieldgen < 0) + self.has_fieldgen *= 0.8; + + if (self.has_fieldgen > 2 && (self.has_fieldgen > (14 - 2*self.has_tesla))) + { + self.has_fieldgen -= 0.1; + return FALSE; + } + + dist = self.enemy.origin - self.origin; + + if (random() < (0.4 - (dist_z / 1000))) + { + return FALSE; + } + + + return TRUE; +}; + + float () CheckShamLightning = { local vector dist; local float d; local float d2; + + if (self.has_sentry < 0) + self.has_sentry *= 0.8; + + if (self.has_sentry > 2 && self.has_sentry > (14 - 2*self.has_tesla)) + { + self.has_sentry -= 0.1; + return FALSE; + } if (!visible2(self.enemy, self)) //If can see return FALSE; @@ -475,38 +568,104 @@ float () CheckShamLightning = dist = self.enemy.origin - self.origin; dist_x = dist_y = 0; //CH only need z d = vlen(dist); - if (self.has_tesla == 1) + if (self.has_tesla > 6 && random() < 0.1) + return TRUE; + if (random() > self.has_tesla * (d2 / 300) * 0.07) //CH as not to fire all the time return FALSE; - if (random() > self.has_tesla * 0.07) //CH as not to fire all the time + if (d2 < 1500 - self.has_tesla * 250 && d < 100) return FALSE; - if (d2 < 1500 - self.has_tesla * 300 && d < 100) + if (d2 > 2000 + self.has_tesla * 200) //Sham has lots of lightning range return FALSE; - if (d2 > 2000 + self.has_tesla * 200) //Min X,Y distance away before zap - return FALSE; - /*if (self.has_tesla > 3 && random() > 0.5) - self.attack_state = AS_FIREBALL; - //else /// OFTEN*/ - self.attack_state = AS_MISSILE; + return TRUE; }; +float() CheckShamConvert = +{ + if (self.has_tesla <= 6) + return FALSE; + if (!IsMonsterNonArmy(self.enemy)) + return FALSE; + if (self.enemy.classname == "monster_shambler" && self.enemy.has_tesla > 6) + return FALSE; + if (Teammate(self.real_owner.team_no, self.enemy.real_owner.team_no)) + return FALSE; + if (self.enemy.health > (self.enemy.max_health * 3 / 4)) + return FALSE; + + if (self.enemy.classname == "monster_shambler" && self.enemy.has_tesla > 5) + { + if (self.enemy.has_tesla > 6 || random() > 0.5) + return FALSE; + } + + if (random() * 4000 < self.enemy.health) + return FALSE; + + sound (self, CHAN_VOICE, "boss1/sight1.wav", 1, ATTN_NORM); + sprint (self.enemy.real_owner, PRINT_HIGH, "Your demon bows before its master!\n"); + + self.enemy.martyr_enemy = self.enemy.real_owner; + self.enemy.real_owner = self.real_owner; + self.enemy.owner = self.real_owner; + self.enemy.is_malfunctioning = TRUE; + self.enemy.enemy = NIL; + self.enemy.think = self.enemy.th_walk; + self.enemy.nextthink = time + 1; + self.enemy.goalentity = self.enemy; + //self.enemy.invincible_finished = self.enemy.nextthink; + + + if (self.enemy.martyr_enemy.demon_one == self.enemy) + { + self.enemy.martyr_enemy.job -= (self.enemy.martyr_enemy.job & JOB_DEMON_OUT); + self.enemy.martyr_enemy.demon_one = NIL; + } + + self.enemy = NIL; + if (self.movetarget) + self.think = self.th_walk; + else + self.think = self.th_stand; +}; + float() ShamCheckAttack = { + if (CheckShamConvert()) + { + self.enemy = NIL; + return FALSE; + } + + if (random() * 10 > self.has_tesla) //don't attack all the time, but do choose correctly if we're attacking. + return FALSE; + // if close enough for slashing, go for it if (CheckShamMelee ()) { self.attack_state = AS_MELEE; return TRUE; } - if (CheckShamLightning ()) + + if (CheckShamFireball ()) + { + self.attack_state = AS_FIREBALL; return TRUE; + } + + if (CheckShamLightning ()) + { + self.attack_state = AS_MISSILE; + return TRUE; + } + return FALSE; }; // Shambler shoots fireballs! -/* + void() sham_fireball = { local float r; @@ -532,8 +691,12 @@ void() sham_fireballl7 =[ $swingl7, sham_fireballl8 ] {ai_charge(15 void() sham_fireballl8 =[ $swingl8, sham_fireballl9 ] {ai_charge(12 * (0.7 + self.has_tesla * 0.2));}; void() sham_fireballl9 =[ $swingl9, sham_run1 ] { ai_charge(24 * (0.7 + self.has_tesla * 0.2)); -if (random() < 0.2) - self.think = sham_fireballr1; + if (random() < 0.2) { + if (!CheckShamMelee()) + self.think = sham_fireballr1; + else + self.think = sham_swingr1; + } }; void() sham_fireballr1 =[ $swingr1, sham_fireballr2 ] { @@ -547,71 +710,172 @@ void() sham_fireballr6 =[ $swingr6, sham_fireballr7 ] {ai_charge(18 void() sham_fireballr7 =[ $swingr7, sham_fireballr8 ] {ai_charge(18 * (0.7 + self.has_tesla * 0.2)); ShamFireball(-250);}; void() sham_fireballr8 =[ $swingr8, sham_fireballr9 ] {ai_charge(9 * (0.7 + self.has_tesla * 0.2));}; void() sham_fireballr9 =[ $swingr9, sham_run1 ] {ai_charge(30 * (0.7 + self.has_tesla * 0.2)); -if (random() < 0.2) - self.think = sham_fireballl1; +if (random() < 0.4) { + if (!CheckShamMelee()) + self.think = sham_fireballl1; + else + self.think = sham_swingl1; +} }; void(float side) ShamFireball = { - local float ldmg; - local vector delta; - local vector offang; local vector org, dir; - + local float mult; + ai_face (); - delta = self.enemy.origin - self.origin; - offang = vectoangles (delta); - makevectors (offang); +#ifdef SHAMBLER_DEBUG + sprint(self.real_owner, PRINT_HIGH, "Throwing fireballs at "); + sprint(self.real_owner, PRINT_HIGH, self.enemy.classname); + sprint(self.real_owner, PRINT_HIGH, "\n"); +#endif + + makevectors (self.angles); // was offang sound (self, CHAN_WEAPON, "hknight/attack1.wav", 1, ATTN_NORM); //Odd, it was already precached - if (side > 0) //CH cause to spawn on side of demon. - org = self.origin + (v_forward * 10) + (v_right * 20); + if (side > 0) //CH cause to spawn on side of demon. GR - and actually outside the bounding box too! + org = self.origin + (v_forward * 40) + (v_right * 20); else - org = self.origin + (v_forward * 10) - (v_right * 20); + org = self.origin + (v_forward * 40) - (v_right * 20); + org_z += 32; +#ifdef SHAMBLER_DEBUG + sprint(self.real_owner, PRINT_HIGH, "org is "); + sprint(self.real_owner, PRINT_HIGH, vtos(org)); +#endif // set missile speed - dir = normalize (v_forward); //CH demons are not good at throwing - dir_z = 0 - dir_z; //Random Z addage - //dir_x = dir_x + (random() - 0.5)*0.05; //Random X addage - //dir_y = dir_y + (random() - 0.5)*0.05; //Random Y addage +//but shamblers are + //dir_z = 0 - dir_z; //Random Z addage + //dir_x = dir_x + (random() - 0.5)*0.20 / self.has_tesla; //Random X addage + //dir_y = dir_y + (random() - 0.5)*0.20 / self.has_tesla; //Random Y addage newmis = spawn (); newmis.owner = self; - newmis.movetype = MOVETYPE_NOCLIP; + newmis.movetype = MOVETYPE_FLYMISSILE; newmis.solid = SOLID_BBOX; - newmis.angles = vectoangles(dir); + newmis.angles = self.angles; + newmis.avelocity = '200 200 200'; + + dir = normalize(self.enemy.origin - org); + mult = 1300 + self.has_tesla*50; + newmis.velocity = dir * mult; newmis.touch = shambler_fire_touch; newmis.weapon = DMSG_DEMON_FIRE; newmis.classname = "demon_fire"; - newmis.think = SUB_Remove; - newmis.nextthink = time + 10; - setmodel (newmis, "progs/lavaball.mdl"); - setsize (newmis, '-8 -16 -8', '20 16 28'); //CH actual mdl bounds -// setsize (newmis, '0 0 0', '0 0 0'); - setorigin (newmis, org); - newmis.velocity = dir * 1000 * (self.has_tesla - 3); -}; -*/ -/*void() shambler_fire_touch = -OFN fireballs out! + newmis.think = shambler_fire_think; + newmis.nextthink = time + 0.1; + newmis.heat = time + 10; + + newmis.oldorigin = self.enemy.origin; + setmodel (newmis, "progs/lavaball.mdl"); +// setsize (newmis, '-4 -8 -4', '4 8 4'); //CH actual mdl bounds GR well not that big + setsize (newmis, '0 0 0', '0 0 0'); + setorigin (newmis, org); + +#ifdef SHAMBLER_DEBUG + sprint(self.real_owner, PRINT_HIGH, ", newmis.origin is "); + sprint(self.real_owner, PRINT_HIGH, vtos(newmis.origin)); + sprint(self.real_owner, PRINT_HIGH, ".\n"); + + sprint(self.real_owner, PRINT_HIGH, "self.enemy.origin is "); + sprint(self.real_owner, PRINT_HIGH, vtos(self.enemy.origin)); + sprint(self.real_owner, PRINT_HIGH, ".\n"); + + sprint(self.real_owner, PRINT_HIGH, "newmis.velocity is "); + sprint(self.real_owner, PRINT_HIGH, vtos(newmis.velocity)); + sprint(self.real_owner, PRINT_HIGH, ", dir is "); + sprint(self.real_owner, PRINT_HIGH, vtos(dir)); + sprint(self.real_owner, PRINT_HIGH, ".\n"); +#endif +}; + + +void() shambler_fire_think = +{ + local float speed; + local vector dir; + + if (self.heat < time) { + dremove(self); + return; + } + + if (vlen(self.oldorigin - self.origin) < vlen(self.velocity) / 3) { + self.think = SUB_Remove; + self.nextthink = self.heat; + return; + } + + speed = vlen(self.velocity); + dir = normalize(self.oldorigin - self.origin); + + self.velocity = dir * speed; + self.nextthink = time + 0.1; +}; + + +void() shambler_fire_touch = { local float fire_dmg; - fire_dmg = 10 + random() * 25; - fire_dmg = fire_dmg * self.owner.has_tesla; - if (pointcontents(self.origin) == CONTENT_SKY) + local entity head; + + fire_dmg = (30 * self.has_tesla) + (random() * 25); + +#ifdef SHAMBLER_DEBUG + sprint(self.owner.real_owner, PRINT_HIGH, "fire_touch at "); + sprint(self.owner.real_owner, PRINT_HIGH, vtos(self.origin)); + sprint(self.owner.real_owner, PRINT_HIGH, ".\n"); +#endif + + if (pointcontents(self.origin) == CONTENTS_SKY) { + self.owner.has_fieldgen += 1; dremove(self); return; } deathmsg = self.weapon; - T_RadiusDamage (self, self.owner, fire_dmg , self.owner); + T_RadiusDamage (self, self.owner, fire_dmg, self.owner); + + head = findradius(self.origin, 10*self.owner.has_tesla); + + if (!head) + self.owner.has_fieldgen += 1; + + while (head) + { + if (head.takedamage) + { + deathmsg = DMSG_FLAME; + + if (head == self.owner) + self.owner.has_fieldgen += 2; + else if (head == self.owner.enemy) // even if it's a teammate + self.owner.has_fieldgen -= 1; + else if (Teammate(head.team_no, self.owner.team_no)) + self.owner.has_fieldgen += 1; + else + self.owner.has_fieldgen -= 1; + + // set 'em on fire + other = head; // i can't believe this works! + Napalm_touch(); + Napalm_touch(); // set them on a lot of fire + if (other.classname == "player") + stuffcmd(other, "bf\nbf\n"); + if (IsBuilding(other)) + TF_T_Damage (head, self, self.owner, 35, TF_TD_NOTTEAM, TF_TD_FIRE); + } + head = head.chain; + } + self.origin = self.origin - 8*normalize(self.velocity); //??? @@ -629,6 +893,6 @@ void(float side) ShamFireball = multicast (self.origin, MULTICAST_PHS); dremove(self); }; -*/ + diff --git a/sniper.qc b/sniper.qc index 3d3f916..cd17de7 100644 --- a/sniper.qc +++ b/sniper.qc @@ -96,6 +96,17 @@ void() SniperSight_Update = self.angles = vectoangles(v_forward); setorigin(self, trace_endpos); + self.v_angle_z = self.owner.v_angle_z; + + local float diff = vlen(self.owner.v_angle - self.v_angle); + + if (diff > 3) diff = 3; + + if (self.owner.heat < diff * 8) + self.owner.heat = diff * 8; + + self.v_angle = self.owner.v_angle; + self.nextthink = time + 0.1; }; //CH used for the rl @@ -147,6 +158,7 @@ void(float type) SniperSight_Create = sight.owner = self; sight.movetype = MOVETYPE_NOCLIP; sight.solid = SOLID_NOT; + sight.v_angle = self.v_angle; setmodel (sight, "progs/sight.spr"); diff --git a/tfort.qc b/tfort.qc index 00b4928..43384e2 100644 --- a/tfort.qc +++ b/tfort.qc @@ -1447,6 +1447,13 @@ void(entity p) TeamFortress_SetSpeed = } if (p.playerclass != PC_UNDEFINED) { + //before anything, speed reductions from armor (no speedy tanks) + if (p.armorvalue > 0) + p.maxspeed *= (0.8 + (0.2 - p.armortype / 5)); + + if (p.armorvalue > 100 && p.maxspeed > 250) // really tanked? cap speed a little + p.maxspeed -= (p.maxspeed - 250) * (p.armorvalue - 100) / 200; + //1st if we have scuba gear ... if (p.tf_items & NIT_SCUBA) { if (p.flags & FL_INWATER) // and are underwater, increase speed diff --git a/triggers.qc b/triggers.qc index e5dfbd3..eebf8ed 100644 --- a/triggers.qc +++ b/triggers.qc @@ -371,6 +371,13 @@ void() tdeath_touch = // frag anyone who teleports in on top of an invincible player if (other.classname == "player") { + if (Teammate(self.owner.team_no, other.team_no)) + { + other.invincible_finished = 0; + TF_T_Damage(other, self, self, other.health + 5000, TF_TD_IGNOREARMOUR, TF_TD_OTHER); + return; + } + if (other.invincible_finished > time) { self.classname = "teledeath2"; self.owner.invincible_finished = 0; @@ -388,7 +395,7 @@ void() tdeath_touch = if (other.health) { - T_Damage(other, self, self, 5000); + TF_T_Damage(other, self, self, other.health + 5000, TF_TD_IGNOREARMOUR, TF_TD_OTHER); } }; diff --git a/warlock.qc b/warlock.qc index 142c5f8..543ae53 100644 --- a/warlock.qc +++ b/warlock.qc @@ -138,29 +138,10 @@ void(float inp) Menu_Demon_Input = local string st; st=GetMonsterName(self.demon_one); - if (self.demon_one.enemy) - { - if (visible2(self.demon_one,self.demon_one.enemy)) - { - sprint(self,PRINT_HIGH,"Your "); - sprint(self,PRINT_HIGH,st); - sprint(self,PRINT_HIGH," is busy trying to kill!\n"); - self.impulse=0; - return; - } - } - - if (self.demon_one.goalentity == self) - { - sprint(self,PRINT_HIGH,"Your "); - sprint(self,PRINT_HIGH,st); - sprint(self,PRINT_HIGH," is already trying to reach your position!\n"); - self.impulse=0; - return; - } - self.demon_one.enemy=NIL;// + self.demon_one.oldenemy=NIL; self.demon_one.goalentity=self; + self.demon_one.movetarget=self; self.demon_one.nextthink=time+0.1; PutMonsterWalk(self.demon_one); @@ -179,20 +160,10 @@ void(float inp) Menu_Demon_Input = local string st; st=GetMonsterName(self.demon_one); - if (self.demon_one.enemy) - { - if (visible2(self.demon_one,self.demon_one.enemy)) - { - sprint(self,PRINT_HIGH,"Your "); - sprint(self,PRINT_HIGH,st); - sprint(self,PRINT_HIGH," is busy tring to kill!\n"); - self.impulse=0; - return; - } - } - self.demon_one.enemy=NIL;// + self.demon_one.enemy=NIL; self.demon_one.oldenemy=NIL;//// self.demon_one.goalentity=self.demon_one; + self.demon_one.movetarget=self.demon_one; self.demon_one.nextthink=time+0.1; PutMonsterWalk(self.demon_one); @@ -212,20 +183,10 @@ void(float inp) Menu_Demon_Input = local string st; st=GetMonsterName(self.demon_one); - if (self.demon_one.enemy) - { - if (visible2(self.demon_one,self.demon_one.enemy)) - { - sprint(self,PRINT_HIGH,"Your "); - sprint(self,PRINT_HIGH,st); - sprint(self,PRINT_HIGH," is busy tring to kill!\n"); - self.impulse=0; - return; - } - } self.demon_one.enemy=NIL;// self.demon_one.oldenemy=NIL;//// self.demon_one.goalentity=NIL; + self.demon_one.movetarget=NIL; self.demon_one.nextthink=time+0.1; PutMonsterStand(self.demon_one); @@ -240,50 +201,38 @@ void(float inp) Menu_Demon_Input = ResetMenu(); self.impulse = 0; } - else if (inp == 2) // knight + else if (inp == 2) // fiend { self.demon_choice = 2; ResetMenu(); self.impulse = 0; } - else if (inp == 3) // fiend + else if (inp >= 3 && inp < 8) // shambler { - self.demon_choice = 3; + self.demon_choice = inp; ResetMenu(); self.impulse = 0; } - /*else if (inp == 4) // hell knight - { - self.demon_choice = 4; - ResetMenu(); - self.impulse = 0; - } - else if (inp == 5) // shambler - { - self.demon_choice = 5; - ResetMenu(); - self.impulse = 0; - }*/ else if (inp == 8) // unsummon { if (self.job & JOB_DEMON_OUT) - { - local string MName; - MName=GetMonsterName(self.demon_one); - - teamprefixsprint(self.team_no, self); - teamsprint(self.team_no,self, self.netname); - teamsprint(self.team_no,self, " unsummons his "); + { + local string MName; + MName=GetMonsterName(self.demon_one); + + teamprefixsprint(self.team_no, self); + teamsprint(self.team_no,self, self.netname); + teamsprint(self.team_no,self, " unsummons his "); - teamsprint(self.team_no,self, MName); - teamsprint(self.team_no,self, "\n"); + teamsprint(self.team_no,self, MName); + teamsprint(self.team_no,self, "\n"); - kill_my_demon(); - } - else return; + kill_my_demon(); + } + else return; - ResetMenu(); + ResetMenu(); self.impulse = 0; return; } @@ -301,9 +250,15 @@ void(float inp) Menu_Demon_Input = #ifndef WARLOCK_TEST + if (self.demon_blood < 8 && self.demon_choice >= 4) + { + self.impulse = 0; + return; + } + if (self.demon_blood < 4 && self.demon_choice == 3) { - sprint (self, PRINT_HIGH, "You need to kill 5 enemies with your knife to summon a shambler.\n"); + sprint (self, PRINT_HIGH, "You need to kill 4 enemies with your knife to summon a shambler.\n"); //ResetMenu(); self.impulse = 0; return; @@ -349,8 +304,30 @@ void(float inp) Menu_Demon_Input = // TEMP points = 5; - - if (self.demon_choice == 3) + + if (self.demon_choice == 5) + { + if (infokey(NIL, "shamking") == "off") + { + self.impulse = 0; + return; + } + points = 4 + self.demon_blood / 4; + self.demon_blood = 0; + self.demon_choice = 3; + } + else if (self.demon_choice == 4) + { + if (infokey(NIL, "bsham") == "off") + { + self.impulse = 0; + return; + } + points = 6; + self.demon_blood = self.demon_blood - 8; + self.demon_choice = 3; + } + else if (self.demon_choice == 3) self.demon_blood = self.demon_blood - 4; else if (self.demon_choice == 2) self.demon_blood = self.demon_blood - 2; @@ -379,7 +356,7 @@ void(float inp) Menu_Demon_Input = SummonTimer = spawn (); SummonTimer.classname = "timer"; SummonTimer.owner = self; - SummonTimer.nextthink = time + 1.5; //Small delays are cool + SummonTimer.nextthink = time + (points * 1.5) - 6 ; //Small delays are cool SummonTimer.think = SummonThink; SummonTimer.has_tesla = points; SummonTimer.heat = 0; @@ -566,7 +543,7 @@ void (float points) custom_demon_create = newmis.classname = "monster_hknight"; newmis.mdl = "progs/hknight.mdl"; }*/ - else if (self.demon_choice == 3) + else if (self.demon_choice >= 3) { newmis.classname = "monster_shambler"; #ifdef no_tf_monsters @@ -628,7 +605,7 @@ void (float points) custom_demon_create = setsize (newmis, VEC_HULL2_MIN, VEC_HULL2_MAX); setorigin (newmis, newmis.origin + '0 0 30'); }*/ - else if (self.demon_choice == 3) + else if (self.demon_choice >= 3) { #ifdef no_tf_monsters setmodel (newmis, "progs/shambler.mdl"); @@ -760,25 +737,32 @@ void (float points) custom_demon_create = } else if ( newmis.classname == "monster_shambler" ) { - newmis.health = SHAMBLER_HP;//750 + points * 350; //WK 300 - newmis.armorclass = 0;// ofn- AT_SAVEEXPLOSION | AT_SAVEMELEE; + newmis.health = (points * 2200) - 7000; //750 + points * 350; //WK 300 + if (newmis.health < 300) newmis.health = 300; + newmis.armorclass = AT_SAVEEXPLOSION;// ofn- AT_SAVEEXPLOSION | AT_SAVEMELEE; newmis.last_saveme_sound = 0; newmis.has_tesla = points; newmis.has_sentry = 0; + newmis.has_fieldgen = 0; newmis.th_stand = sham_stand1; newmis.th_walk = sham_walk1; - newmis.th_run = sham_run1; + newmis.th_run = sham_run; newmis.th_die = custom_shambler_die; newmis.th_melee = sham_melee; // one of two attacks newmis.th_missile = sham_magic1; newmis.th_pain = sham_pain; - //newmis.th_fireball = sham_fireball; //- OfN - this, uglyness apart, didn't work anyway + newmis.th_fireball = sham_fireball; //- OfN - this, uglyness apart, didn't work anyway newmis.think = walkmonster_start; newmis.nextthink = time + 1; //newmis.touch = Demon_JumpTouch; //newmis.touch = NIL; ////newmis.real_owner.demon_blood = 0; marduk bug - sprint(self, PRINT_HIGH, "You summon a shambler.\n"); + if (newmis.has_tesla > 6) + sprint (self, PRINT_HIGH, "You summon a shambler king.\n"); + else if (newmis.has_tesla == 6) + sprint (self, PRINT_HIGH, "You summon a battle shambler.\n"); + else + sprint(self, PRINT_HIGH, "You summon a shambler.\n"); } else { @@ -802,6 +786,7 @@ void (float points) custom_demon_create = } newmis.touch=MonsterTouch; + newmis.is_malfunctioning = 0; newmis.message = "XX"; // flag to identify monsters/army for sentry targetting @@ -949,7 +934,7 @@ void () kill_my_demon = while (te) { - if (te.real_owner == self) + if (te.real_owner == self && !te.is_malfunctioning) { oself = self; self = te; @@ -1084,21 +1069,21 @@ void () kill_my_demon = { if (te.real_owner == self) { - oself = self; - self = te; - ThrowGib ("progs/h_shams.mdl", -100); - ThrowGib ("progs/gib1.mdl", -10); - ThrowGib ("progs/gib3.mdl", -30); - ThrowGib ("progs/gib3.mdl", -70); - sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); - te.think = SUB_Remove; - te.touch = NIL; - te.nextthink = time + 0.1; - self = oself; + oself = self; + self = te; + ThrowGib ("progs/h_shams.mdl", -100); + ThrowGib ("progs/gib1.mdl", -10); + ThrowGib ("progs/gib3.mdl", -30); + ThrowGib ("progs/gib3.mdl", -70); + sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); + te.think = SUB_Remove; + te.touch = NIL; + te.nextthink = time + 0.1; + self = oself; - //self.job = self.job - (self.job & JOB_DEMON_OUT); - sprint (self, PRINT_HIGH, "Your shambler is dead.\n"); - //TF_T_Damage(te, NIL, NIL, 4000, 0, 0); + //self.job = self.job - (self.job & JOB_DEMON_OUT); + sprint (self, PRINT_HIGH, "Your shambler is dead.\n"); + //TF_T_Damage(te, NIL, NIL, 4000, 0, 0); } te = find(te, classname, "monster_shambler"); } @@ -1129,11 +1114,12 @@ void () kill_my_demon = te = find(te, classname, "monster_wizard"); } - self.job = self.job - (self.job & JOB_DEMON_OUT); - self.demon_one = NIL; - self.summon_one = NIL; - self.summon_two = NIL; + self.job = self.job - (self.job & JOB_DEMON_OUT); + self.demon_one = NIL; + + self.summon_one = NIL; + self.summon_two = NIL; }; void() MonsterTouch = diff --git a/weapons.qc b/weapons.qc index 3779656..61e5301 100644 --- a/weapons.qc +++ b/weapons.qc @@ -1,3 +1,4 @@ + /*====================================================== WEAPONS.QC Custom TeamFortress v3.1 @@ -1215,12 +1216,20 @@ void() W_FireSniperRifle = { local vector dir, src; local float dam_mult, zdif, use_this; + local vector angle; sound (self ,CHAN_WEAPON, "weapons/sniper.wav", 1, ATTN_NORM); KickPlayer(-2, self); // self.currentammo = self.ammo_shells = self.ammo_shells - 1; // ofn moved! - makevectors(self.v_angle); + angle = self.v_angle; + + if (self.heat > 0) { + angle_x += (random() * 0.18 * self.heat) - (0.09 * self.heat); + angle_y += (random() * 0.18 * self.heat) - (0.09 * self.heat); + } + + makevectors(angle); src = self.origin + v_forward * 10; src_z = self.absmin_z + self.size_z * 0.7; @@ -1248,15 +1257,12 @@ void() W_FireSniperRifle = dam_mult = 1; //- OfN - float factor to handle OTR bullets difference - local float is_OTR; // factor of dmg 1 no otr, >1 yes - is_OTR=1; if (self.cutf_items & CUTF_OTR && self.ammo_shells > 2) { - is_OTR = OTR_DMGFACTOR; self.currentammo = self.ammo_shells = self.ammo_shells - 3; } else self.currentammo = self.ammo_shells = self.ammo_shells - 1; - dam_mult=dam_mult*is_OTR; + dam_mult=dam_mult*OTR_DMGFACTOR; if (trace_ent) { if (trace_ent.classname == "player") { @@ -1282,25 +1288,34 @@ void() W_FireSniperRifle = trace_ent.head_shot_vector = '0 0 0'; if (zdif < 0) { - // leg shot - dam_mult = 0.75; + // leg shot doesn't hurt very much + dam_mult = 0.40; - trace_ent.leg_damage = trace_ent.leg_damage + 1; + if (trace_ent.armorvalue < 0.8) + trace_ent.leg_damage++; //- OfN - OTR bullets do twice damage ----------// - if (self.cutf_items & CUTF_OTR) { - dam_mult=dam_mult*is_OTR; - trace_ent.leg_damage = trace_ent.leg_damage + 1; - } + if (self.cutf_items & CUTF_OTR) { + trace_ent.leg_damage++; + } TeamFortress_SetSpeed(trace_ent); deathmsg = DMSG_SNIPERLEGSHOT; //WK Kevlar ignored for snipers again. - TF_T_Damage (trace_ent, self, self, self.heat * dam_mult, 0, 0); + //GR red armor has leg protection + if (trace_ent.armortype >= 0.7 && trace_ent.armorvalue > 0) { + if (self.cutf_items & CUTF_OTR) // otr does extra damage to armored + TF_T_Damage (trace_ent, self, self, OTR_DMG * dam_mult, TF_TD_IGNOREARMOUR, TF_TD_SHOT); + TF_T_Damage (trace_ent, self, self, SNIPER_DMG * dam_mult, 0, TF_TD_SHOT); + } else { + if (self.cutf_items & CUTF_OTR) + TF_T_Damage (trace_ent, self, self, OTR_DMG * dam_mult, TF_TD_IGNOREARMOUR, 0); + TF_T_Damage (trace_ent, self, self, SNIPER_DMG * dam_mult, TF_TD_IGNOREARMOUR,0); + } if (trace_ent.health > 0) { - if (is_OTR > 1) { + if (self.cutf_items & CUTF_OTR) { sprint(trace_ent, PRINT_MEDIUM, "Leg injury! That was OTR stuff!\n"); sprint(self, PRINT_MEDIUM, "OTR Leg shot - that'll slow him down!\n"); } else { //- not OTR.. @@ -1314,20 +1329,26 @@ void() W_FireSniperRifle = // head shot dam_mult = 2; - //- OfN - OTR bullets do twice damage - dam_mult= dam_mult * is_OTR; - stuffcmd(trace_ent, "bf\n"); trace_ent.head_shot_vector = trace_ent.origin - self.origin; deathmsg = DMSG_SNIPERHEADSHOT; - TF_T_Damage (trace_ent, self, self, self.heat * dam_mult, 0, TF_TD_SHOT); + if (trace_ent.armortype > 0.5 && trace_ent.armorvalue > 0) + { + if (self.cutf_items & CUTF_OTR) // OTR does extra damage to armored + TF_T_Damage (trace_ent, self, self, OTR_DMG * dam_mult, TF_TD_IGNOREARMOUR, TF_TD_SHOT); + TF_T_Damage (trace_ent, self, self, SNIPER_DMG * dam_mult, 0, TF_TD_SHOT); + } else { + if (self.cutf_items & CUTF_OTR) + TF_T_Damage (trace_ent, self, self, OTR_DMG * dam_mult, TF_TD_IGNOREARMOUR, 0); + TF_T_Damage (trace_ent, self, self, SNIPER_DMG * dam_mult, TF_TD_IGNOREARMOUR, 0); + } if (trace_ent.health > 0) { - if (is_OTR > 1) { + if (self.cutf_items & CUTF_OTR) { sprint(trace_ent, PRINT_MEDIUM, "Head injury! That was OTR stuff!\n"); sprint(self, PRINT_MEDIUM, "OTR Head shot - that's gotta hurt!\n"); - } else { + } else { sprint(trace_ent, PRINT_MEDIUM, "Head injury!\n"); sprint(self, PRINT_MEDIUM, "Head shot - that's gotta hurt!\n"); } @@ -1336,6 +1357,12 @@ void() W_FireSniperRifle = return; } else deathmsg = DMSG_SNIPERRIFLE; + if (self.cutf_items & CUTF_OTR) { + if (trace_ent.armorvalue > 0) + TF_T_Damage (trace_ent, self, self, OTR_DMG * dam_mult, TF_TD_IGNOREARMOUR, TF_TD_SHOT); + else + TF_T_Damage (trace_ent, self, self, OTR_DMG * dam_mult, TF_TD_IGNOREARMOUR, 0); + } } } @@ -1344,7 +1371,7 @@ void() W_FireSniperRifle = if (trace_fraction == 1.0) TraceAttack (0, dir); else // if it hit something - TraceAttack (self.heat * dam_mult, dir); + TraceAttack (SNIPER_DMG * dam_mult, dir); ApplyMultiDamage (); Multi_Finish (FALSE); @@ -1355,19 +1382,33 @@ void() W_FireSniperRifle = TeamFortress : W_FireAutoRifle =================================== */ +// same as sniper rifle void() W_FireAutoRifle = { - local vector dir; +#ifndef OLD_AUTORIFLE + if (self.heat <= 0) + self.heat = 0; + + self.heat += 5; + + if (self.heat > 1000) + self.heat = 1000; + + W_FireSniperRifle(); +#else + local vector angle; sound (self ,CHAN_WEAPON, "weapons/sniper.wav", 1, ATTN_NORM); KickPlayer(-1, self); self.currentammo = self.ammo_shells = self.ammo_shells - 1; + makevectors(self.v_angle); dir = v_forward; deathmsg = DMSG_AUTORIFLE; FireSniperBullet (dir, 8); +#endif }; /* @@ -2874,7 +2915,7 @@ void() W_Attack = } else if (self.current_weapon == WEAP_AUTO_RIFLE) { player_autorifle1(); W_FireAutoRifle(); - Attack_Finished(0.1); + Attack_Finished(0.2); } else if (self.current_weapon == WEAP_ASSAULT_CANNON) { // Need 4 cells to power up the Assault Cannon if (self.ammo_cells < 4) { @@ -3318,11 +3359,18 @@ void() W_ChangeWeapon = } } if (fl == WEAP_DAEDALUS) { if (self.ammo_cells < 5) - am = 1; - } else if (fl == WEAP_LIGHTNING) { + { + if (it & WEAP_LIGHTNING) + fl = WEAP_LIGHTNING; + else am = 1; + } + } if (fl == WEAP_LIGHTNING) { if (self.ammo_cells < 1) - am = 1; - } + am = 1; + } if (it & WEAP_AIRF && am) { + fl = WEAP_AIRF; + am = 0; + } } else if (self.impulse == TF_MEDIKIT) { fl = WEAP_MEDIKIT; @@ -3852,6 +3900,15 @@ void() DeadImpulses = return; } + if (self.impulse == 69 && infokey(NIL, "lock_cheat") == "yes") + { + self.demon_blood = MAX_KNIFE_BLOOD; + self.job = self.job | JOB_BLOODY_KNIFE; + self.impulse=0; + return; + } + + // if (self.impulse == I_CHEAT_ONE) { I_DID_CHEAT_ONE(); @@ -4024,8 +4081,9 @@ void() W_WeaponFrame = Attack_Finished(0.2); } else if (self.current_weapon == WEAP_SNIPER_RIFLE) { if (self.tfstate & TFSTATE_AIMING) { - if (self.heat < 400) - self.heat = self.heat + 3; + self.heat--; + if (self.heat < (vlen(self.velocity) * 0.1)) + self.heat = vlen(self.velocity) * 0.1; if (self.height > 30) { self.height = self.height - 5; @@ -4038,7 +4096,8 @@ void() W_WeaponFrame = if (vlen(tv) <= WEAP_SNIPER_RIFLE_MAX_MOVE) { // create the laser sight SniperSight_Create(0); - self.heat = 50; // damage done + self.heat = 100; // damage done + // GR no, charging sniper rifle makes no sense, idiot #ifdef WEINER_SNIPER self.heat = 80; #endif @@ -4088,6 +4147,11 @@ void() W_WeaponFrame = TeamFortress_SetSpeed(self); player_run (); + } else if (self.current_weapon == WEAP_AUTO_RIFLE) { + self.heat *= 0.2; + self.heat -= 1; + if (self.heat < 30) + self.heat = 30; // auto can't be as accurate } }; diff --git a/wizard.qc b/wizard.qc index 86ecb01..9476834 100644 --- a/wizard.qc +++ b/wizard.qc @@ -356,7 +356,7 @@ void() wiz_death8 =[ $death8, wiz_death8 ] void() wiz_die = { - if (self.real_owner.classname == "player") + if (self.real_owner.classname == "player" && self.real_owner.demon_one == self) { sprint(self.real_owner,PRINT_HIGH,"Your scrag is dead.\n"); self.real_owner.job = self.real_owner.job - (self.real_owner.job & JOB_DEMON_OUT);