<Grievre> lemme see... fixes: stuck shamblers, cheat teslas, camming and

sensing
<Grievre> give mirvs the right death message, make them a little weaker and
more spread out
<Grievre> increased damage done by exp body... fixes not being able to use
airfist if you have daedalus or lg with no cells
<Grievre> 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
<Grievre> you lose speed the more armor you have (so upgraded people can
buy cougar and cheetah now)
<Grievre> attempted to fix the respawn guard not telefragging bug (if it
was still there)
<Grievre> 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
<Grievre> (works for all demons)
<Grievre> made it so a monster goes back to what it was doing before
(following you, patrolling etc) once it's done with its enemy
<Grievre> 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.
<Grievre> autorifle now has half the rate of fire but does same damage as
sniper rifle, but less accurate
<Grievre> headshots always ignore armor if target has green armor, legshots
always ignore armor except for red
<Grievre> added bshams and shambler kings (can be disabled with infokeys)
<Grievre> increased max knife blood to 32
<Grievre> 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
<Grievre> made shamblers a little smarter and more powerful in general
<Grievre> they now attack buildings (only bshams/kings) if they are
attacked by them first
<Grievre> bsham/king fireball now sets things on fire
<Grievre> shamblers will generally attack the person who last hit them
<Grievre> shortened judoka range (they have the old range if they get close
combat
<Grievre> 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)
<Grievre> fixed shambler fireball so it doesn't miss and hurt itself so
much
<Grievre> #define OLD_AUTORIFLE
<Grievre> will go to the old behavior of the auto rifle
<Grievre> I think that's it
<Grievre> oh, I changed the intro message and version string a little, you
might want to change that
This commit is contained in:
Bill Currie 2003-11-12 04:58:19 +00:00
parent f865e4e952
commit a365e00b22
23 changed files with 738 additions and 333 deletions

23
ai.qc
View file

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

View file

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

View file

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

View file

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

View file

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

47
jobs.qc
View file

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

View file

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

View file

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

View file

@ -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®telefragged®com¯shaka"
#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 óC”
//#define MSG_CUTFVERSION "CustomÔÆ version ö3®2®OfN"
#define MSG_CUTFVERSION "ÐÒÏÚÁÃ CustomÔÆ ö3®2®OfN4"
#define MSG_CUTFVERSION "ÐÒÏÚÁÃ CustomÔÆ ö3®2®OfN4-qfcc-GR3"
// Comments CenterPrinted when a player gets the CTF flag
#define MSG_CTF_FLAG_GRAB_TEAM1 "You got the enemy flag!\n\nFlee!"

View file

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

View file

@ -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, " (");

View file

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

View file

@ -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")

View file

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

View file

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

View file

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

View file

@ -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,13 +154,20 @@ 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;
@ -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,22 +496,70 @@ 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;
dist = self.enemy.origin - self.origin;
@ -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);
};
*/

View file

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

View file

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

View file

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

View file

@ -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);
{
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 ");
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;
@ -350,7 +305,29 @@ 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 =

View file

@ -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,10 +3359,17 @@ 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;
}
//<CH>
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
}
};

View file

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