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