Added monster_gunner_commander to missionpack DLL.

Added monster_fire_flechette() and monster_fire_prox() functions to g_monster.c in missionpack DLL.
Refactored prox weapon code in missionpack DLL.
Added grenade evasion for monster-fired prox mines.
Added FL2_COMMANDER moreflag for medic commander and deadalus in missionpack DLL.
Added precache of hand grenade model to grenade ammo in g_items.c in default Lazarus DLL and missionpack DLL.
This commit is contained in:
Knightmare66 2021-04-23 05:08:26 -04:00
parent 0a54aa8423
commit 4b6e68fcd2
20 changed files with 502 additions and 293 deletions

View file

@ -524,7 +524,7 @@ qboolean Pickup_AmmogenPack (edict_t *ent, edict_t *other)
if (!ent || !other)
return false;
//Knightmare- override ammo pickup values with cvars
// Knightmare- override ammo pickup values with cvars
SetAmmoPickupValues ();
item = FindItem("Bullets");
@ -1986,7 +1986,7 @@ always owned, never in the world
WEAP_GRENADES,
NULL,
AMMO_GRENADES,
/* precache */ "weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav "
/* precache */ "models/objects/grenade2/tris.md2 weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav "
},
/*QUAKED weapon_grenadelauncher (.3 .3 1) (-16 -16 -16) (16 16 16)
@ -2974,7 +2974,7 @@ tank commander's head
"item_flag_team3",
CTFPickup_Flag,
NULL,
CTFDrop_Flag, //Should this be null if we don't want players to drop it manually?
CTFDrop_Flag, // Should this be null if we don't want players to drop it manually?
NULL,
"ctf/flagtk.wav",
#ifdef KMQUAKE2_ENGINE_MOD
@ -3000,7 +3000,7 @@ tank commander's head
"item_tech1",
CTFPickup_Tech,
NULL,
CTFDrop_Tech, //Should this be null if we don't want players to drop it manually?
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
NULL,
"items/pkup.wav",
"models/ctf/resistance/tris.md2", 0, EF_ROTATE,
@ -3022,7 +3022,7 @@ tank commander's head
"item_tech2",
CTFPickup_Tech,
NULL,
CTFDrop_Tech, //Should this be null if we don't want players to drop it manually?
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
NULL,
"items/pkup.wav",
"models/ctf/strength/tris.md2", 0, EF_ROTATE,
@ -3044,7 +3044,7 @@ tank commander's head
"item_tech3",
CTFPickup_Tech,
NULL,
CTFDrop_Tech, //Should this be null if we don't want players to drop it manually?
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
NULL,
"items/pkup.wav",
"models/ctf/haste/tris.md2", 0, EF_ROTATE,
@ -3066,7 +3066,7 @@ tank commander's head
"item_tech4",
CTFPickup_Tech,
NULL,
CTFDrop_Tech, //Should this be null if we don't want players to drop it manually?
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
NULL,
"items/pkup.wav",
"models/ctf/regeneration/tris.md2", 0, EF_ROTATE,
@ -3088,7 +3088,7 @@ tank commander's head
"item_tech5",
CTFPickup_Tech,
NULL,
CTFDrop_Tech, //Should this be null if we don't want players to drop it manually?
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
NULL,
"items/pkup.wav",
"models/ctf/vampire/tris.md2", 0, EF_ROTATE,
@ -3110,7 +3110,7 @@ tank commander's head
"item_tech6",
CTFPickup_Tech,
NULL,
CTFDrop_Tech, //Should this be null if we don't want players to drop it manually?
CTFDrop_Tech, // Should this be null if we don't want players to drop it manually?
NULL,
"items/pkup.wav",
"models/ctf/ammogen/tris.md2", 0, EF_ROTATE,
@ -3127,7 +3127,7 @@ tank commander's head
/* precache */ "ctf/tech6.wav"
},
/* Ammogen-spawned Backpack*/
/* Ammogen-spawned Backpack */
{
"item_ammogen_pack",
Pickup_AmmogenPack,

View file

@ -560,7 +560,7 @@ void M_ReactToDamage (edict_t *targ, edict_t *attacker, edict_t *inflictor)
// also, target the tesla if it's a "new" tesla
if ((inflictor) && (!strcmp(inflictor->classname, "tesla")))
{
new_tesla = MarkTeslaArea(targ, inflictor);
new_tesla = MarkTeslaArea (targ, inflictor);
if (new_tesla)
TargetTesla (targ, inflictor);
return;
@ -978,7 +978,7 @@ void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_
}
// If targ is a remote turret_driver and attacker is a player, replace turret_driver
// with normal infantry dude and turn TRACK off on corresponding turret_breach
if ( targ->classname && !Q_stricmp(targ->classname,"turret_driver") &&
if ( targ->classname && !Q_stricmp(targ->classname, "turret_driver") &&
(targ->spawnflags & 1) && (attacker->client) )
{
edict_t *monster;
@ -1076,9 +1076,9 @@ void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_
// Shamblers take half damage from explosives
if ( (targ->svflags & SVF_MONSTER) &&
( (Q_stricmp(targ->classname,"q1_monster_shambler") == 0) || (Q_stricmp(targ->classname,"monster_q1_shambler") == 0) ) &&
( (Q_stricmp(inflictor->classname, "grenade") == 0) || (Q_stricmp(inflictor->classname, "prox") == 0) ||
(Q_stricmp(inflictor->classname, "plasma") == 0) ||
(Q_stricmp(inflictor->classname, "rocket") == 0) || (Q_stricmp(inflictor->classname, "homing rocket") == 0) ) )
( (Q_stricmp(inflictor->classname, "grenade") == 0) || (Q_stricmp(inflictor->classname, "hgrenade") == 0)
|| (Q_stricmp(inflictor->classname, "prox") == 0) || (Q_stricmp(inflictor->classname, "plasma") == 0)
|| (Q_stricmp(inflictor->classname, "rocket") == 0) || (Q_stricmp(inflictor->classname, "homing rocket") == 0) ) )
damage = (int)((float)damage * 0.5f);
// Skid - q1 monsters don't go flying

View file

@ -2149,7 +2149,7 @@ extern void fire_player_melee ( edict_t * self , vec3_t start , vec3_t aim , int
extern void SP_prox ( edict_t * prox ) ;
extern void prox_delayed_start ( edict_t * prox ) ;
extern void Cmd_DetProx_f ( edict_t * ent ) ;
extern void fire_prox ( edict_t * self , vec3_t start , vec3_t aimdir , int damage_multiplier , int speed ) ;
extern void fire_prox ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int damage_multiplier , int speed , int health , float timer , float damage_radius ) ;
extern void prox_land ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ;
extern void prox_open ( edict_t * ent ) ;
extern void prox_seek ( edict_t * ent ) ;
@ -2272,6 +2272,8 @@ extern void M_FlyCheck ( edict_t * self ) ;
extern void M_FliesOn ( edict_t * self ) ;
extern void M_FliesOff ( edict_t * self ) ;
extern void monster_fire_plasma_rifle ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , int flashtype , qboolean spread ) ;
extern void monster_fire_prox ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int damage_multiplier , int speed , int health , float timer , float damage_radius , int flashtype ) ;
extern void monster_fire_flechette ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , float damage_radius , int radius_damage , int flashtype ) ;
extern void monster_fire_heat ( edict_t * self , vec3_t start , vec3_t dir , vec3_t offset , int damage , int kick , int flashtype ) ;
extern void monster_fire_tracker ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , edict_t * enemy , int flashtype ) ;
extern void monster_fire_blaster2 ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , int flashtype , int effect ) ;

View file

@ -2272,6 +2272,8 @@
{"M_FliesOn", (byte *)M_FliesOn},
{"M_FliesOff", (byte *)M_FliesOff},
{"monster_fire_plasma_rifle", (byte *)monster_fire_plasma_rifle},
{"monster_fire_prox", (byte *)monster_fire_prox},
{"monster_fire_flechette", (byte *)monster_fire_flechette},
{"monster_fire_heat", (byte *)monster_fire_heat},
{"monster_fire_tracker", (byte *)monster_fire_tracker},
{"monster_fire_blaster2", (byte *)monster_fire_blaster2},

View file

@ -2825,7 +2825,7 @@ gitem_t itemlist[] =
WEAP_GRENADES,
NULL,
AMMO_GRENADES,
"weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav" // precache
"models/objects/grenade2/tris.md2 weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav" // precache
},
// 16

View file

@ -135,6 +135,7 @@
#define FL2_TURRET_DOUBLE_ALT 0x00000002 // this turret alternates firing its barrels (style is set)
#define FL2_TURRET_DOUBLE_ALT_FIRING 0x00000004 // secondary barrel in use for alternate firing
#define FL2_CRUCIFIED 0x00000008 // insane is crucified
#define FL2_COMMANDER 0x00000008 // Gunner Commander internal flag
#define FL2_WEAPON_ALT 0x00000010 // plasma guard has spread mode
#define FL2_DO_NOT_REFLECT 0x00000020 // do not reflect this entity
@ -1380,7 +1381,11 @@ void monster_fire_tracker (edict_t *self, vec3_t start, vec3_t dir, int damage,
void monster_fire_heat (edict_t *self, vec3_t start, vec3_t dir, vec3_t offset, int damage, int kick, int flashtype);
// ROGUE
void monster_fire_plasma_rifle (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, qboolean spread); // SKWiD MOD
// Knightmare added
void monster_fire_flechette (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage, int flashtype);
void monster_fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int damage_multiplier, int speed, int health, float timer, float damage_radius, int flashtype);
// SKWiD MOD
void monster_fire_plasma_rifle (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, qboolean spread);
void M_droptofloor (edict_t *ent);
void monster_think (edict_t *self);
@ -1501,6 +1506,8 @@ void Trap_Explode (edict_t *ent);
// Lazarus
qboolean AimGrenade (edict_t *launcher, vec3_t start, vec3_t target, vec_t speed, vec3_t aim);
void Grenade_Evade (edict_t *monster);
void Grenade_Add_To_Chain (edict_t *grenade);
void Grenade_Remove_From_Chain (edict_t *grenade);
//
// g_weapon_q1.c
@ -1732,7 +1739,8 @@ void kick_attack (edict_t *ent);
//
//extern float nuke_framenum;
void fire_flechette (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage);
void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed);
//void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed);
void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int damage_multiplier, int speed, int health, float timer, float damage_radius);
void fire_nuke (edict_t *self, vec3_t start, vec3_t aimdir, int speed);
void fire_nbomb (edict_t *self, vec3_t start, vec3_t aimdir, int speed);
void fire_flame (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed);

View file

@ -486,6 +486,28 @@ void monster_fire_heat (edict_t *self, vec3_t start, vec3_t dir, vec3_t offset,
}
// ROGUE
// Knightmare added
void monster_fire_flechette (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage, int flashtype)
{
fire_flechette (self, start, dir, damage, speed, damage_radius, radius_damage);
gi.WriteByte (svc_muzzleflash2);
gi.WriteShort (self - g_edicts);
gi.WriteByte (flashtype);
gi.multicast (start, MULTICAST_PVS);
}
void monster_fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int damage_multiplier, int speed, int health, float timer, float damage_radius, int flashtype)
{
fire_prox (self, start, aimdir, damage, damage_multiplier, speed, health, timer, damage_radius);
gi.WriteByte (svc_muzzleflash2);
gi.WriteShort (self - g_edicts);
gi.WriteByte (flashtype);
gi.multicast (start, MULTICAST_PVS);
}
// end Knightmare
// SKWiD MOD
void monster_fire_plasma_rifle (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, qboolean spread)
{
@ -939,9 +961,9 @@ void M_MoveFrame (edict_t *self)
mmove_t *move;
int index;
// Lazarus: For live monsters weaker than gladiator who aren't already running from
// Lazarus: For live monsters weaker than the tank who aren't already running from
// something, evade live grenades on the ground.
if ((self->health > 0) && (self->max_health < 400) && !(self->monsterinfo.aiflags & AI_CHASE_THING) && self->monsterinfo.run)
if ((self->health > 0) && (self->max_health < 750) && !(self->monsterinfo.aiflags & AI_CHASE_THING) && self->monsterinfo.run) // was self->max_health < 400
Grenade_Evade (self);
move = self->monsterinfo.currentmove;
@ -1659,6 +1681,7 @@ int PatchMonsterModel (char *modelname)
qboolean is_gekk = false;
qboolean is_fixbot = false;
qboolean is_chick = false;
qboolean is_gunner = false;
qboolean is_soldierh = false;
qboolean is_carrier = false;
qboolean is_hover = false;
@ -1724,6 +1747,11 @@ int PatchMonsterModel (char *modelname)
is_chick = true;
numskins = 16;
}
else if (!strcmp(modelname, "models/monsters/gunner/tris.md2"))
{
is_gunner = true;
numskins = 16;
}
else if (!strcmp(modelname, "models/monsters/soldierh/tris.md2"))
{
is_soldierh = true;
@ -2021,6 +2049,44 @@ int PatchMonsterModel (char *modelname)
Com_strcat (skins[j], sizeof(skins[j]), "custombeta_p3.pcx"); break;
}
}
else if (is_gunner)
{
switch (j)
{
case 0:
Com_strcat (skins[j], sizeof(skins[j]), "skin.pcx"); break;
case 1:
Com_strcat (skins[j], sizeof(skins[j]), "pain.pcx"); break;
case 2:
Com_strcpy (skins[j], sizeof(skins[j]), "comm_skin.pcx"); break;
case 3:
Com_strcpy (skins[j], sizeof(skins[j]), "comm_pain.pcx"); break;
case 4:
Com_strcat (skins[j], sizeof(skins[j]), "custom1.pcx"); break;
case 5:
Com_strcat (skins[j], sizeof(skins[j]), "custompain1.pcx"); break;
case 6:
Com_strcat (skins[j], sizeof(skins[j]), "custombeta1.pcx"); break;
case 7:
Com_strcat (skins[j], sizeof(skins[j]), "custombeta_p1.pcx"); break;
case 8:
Com_strcat (skins[j], sizeof(skins[j]), "custom2.pcx"); break;
case 9:
Com_strcat (skins[j], sizeof(skins[j]), "custompain2.pcx"); break;
case 10:
Com_strcat (skins[j], sizeof(skins[j]), "custombeta2.pcx"); break;
case 11:
Com_strcat (skins[j], sizeof(skins[j]), "custombeta_p2.pcx"); break;
case 12:
Com_strcat (skins[j], sizeof(skins[j]), "custom3.pcx"); break;
case 13:
Com_strcat (skins[j], sizeof(skins[j]), "custompain3.pcx"); break;
case 14:
Com_strcat (skins[j], sizeof(skins[j]), "custombeta3.pcx"); break;
case 15:
Com_strcat (skins[j], sizeof(skins[j]), "custombeta_p3.pcx"); break;
}
}
else if (is_soldierh)
{
switch (j)

View file

@ -1347,7 +1347,7 @@ edict_t *CheckForBadArea(edict_t *ent)
#define TESLA_DAMAGE_RADIUS 128
qboolean MarkTeslaArea(edict_t *self, edict_t *tesla)
qboolean MarkTeslaArea (edict_t *self, edict_t *tesla)
{
vec3_t mins, maxs;
edict_t *e;
@ -1367,7 +1367,7 @@ qboolean MarkTeslaArea(edict_t *self, edict_t *tesla)
tail = tail->teamchain;
if (!strcmp(e->classname, "bad_area"))
{
// gi.dprintf("tesla already has a bad area marked\n");
// gi.dprintf("tesla already has a bad area marked\n");
return false;
}
e = e->teamchain;
@ -1380,8 +1380,8 @@ qboolean MarkTeslaArea(edict_t *self, edict_t *tesla)
trigger = tesla->teamchain;
// VectorAdd (trigger->s.origin, trigger->mins, mins);
// VectorAdd (trigger->s.origin, trigger->maxs, maxs);
// VectorAdd (trigger->s.origin, trigger->mins, mins);
// VectorAdd (trigger->s.origin, trigger->maxs, maxs);
VectorCopy(trigger->absmin, mins);
VectorCopy(trigger->absmax, maxs);
@ -1397,18 +1397,19 @@ qboolean MarkTeslaArea(edict_t *self, edict_t *tesla)
VectorSet (mins, -TESLA_DAMAGE_RADIUS, -TESLA_DAMAGE_RADIUS, tesla->mins[2]);
VectorSet (maxs, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS);
area = SpawnBadArea(mins, maxs, 30, tesla);
area = SpawnBadArea (mins, maxs, 30, tesla);
}
// if we spawned a bad area, then link it to the tesla
if (area)
{
// gi.dprintf("bad area marker spawned and linked to tesla\n");
// gi.dprintf("bad area marker spawned and linked to tesla\n");
tail->teamchain = area;
}
return true;
}
// predictive calculator
// target is who you want to shoot
// start is where the shot comes from

View file

@ -42,7 +42,7 @@ void flechette_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t
if (other->takedamage)
{
//gi.dprintf("t_damage %s\n", other->classname);
// gi.dprintf("t_damage %s\n", other->classname);
T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal,
self->dmg, self->dmg_radius, DAMAGE_NO_REG_ARMOR, MOD_ETF_RIFLE);
}
@ -64,7 +64,7 @@ void flechette_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t
// T_RadiusDamage(self, self->owner, 24, self, 48, MOD_ETF_RIFLE);
}
//Knightmare- added splash damage
// Knightmare- added splash damage
T_RadiusDamage(self, self->owner, self->radius_dmg, self, self->dmg_radius, MOD_ETF_SPLASH);
G_FreeEdict (self);
@ -279,9 +279,11 @@ void Prox_Explode (edict_t *ent)
edict_t *owner;
int type;
Grenade_Remove_From_Chain (ent);
// free the trigger field
//PMM - changed teammaster to "mover" .. owner of the field is the prox
// PMM - changed teammaster to "mover" .. owner of the field is the prox
if (ent->teamchain && ent->teamchain->owner == ent)
G_FreeEdict(ent->teamchain);
@ -293,16 +295,19 @@ void Prox_Explode (edict_t *ent)
}
// play quad sound if appopriate
if (ent->dmg > sk_prox_damage->value)
// if (ent->dmg > sk_prox_damage->value)
if (ent->count > 1) // Knightmare- use stored multiplier
{
if (ent->dmg < (4 * sk_prox_damage->value)) //double sound
// if (ent->dmg < (4 * sk_prox_damage->value)) // double sound
if (ent->count < 4) // double sound
gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage3.wav"), 1, ATTN_NORM, 0);
else //quad sound
else // quad sound
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
}
ent->takedamage = DAMAGE_NO;
T_RadiusDamage(ent, owner, ent->dmg, ent, sk_prox_radius->value, MOD_PROX);
// T_RadiusDamage(ent, owner, ent->dmg, ent, sk_prox_radius->value, MOD_PROX);
T_RadiusDamage(ent, owner, ent->dmg, ent, ent->dmg_radius, MOD_PROX);
VectorMA (ent->s.origin, -0.02, ent->velocity, origin);
if (ent->groundentity)
@ -326,7 +331,7 @@ void Prox_Explode (edict_t *ent)
//===============
void prox_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
//gi.dprintf("prox_die\n");
// gi.dprintf("prox_die\n");
// if set off by another prox, delay a little (chained explosions)
if (strcmp(inflictor->classname, "prox"))
{
@ -347,10 +352,9 @@ void Prox_Field_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t
{
edict_t *prox;
if (!(other->svflags & SVF_MONSTER) && !other->client)
if ( !(other->svflags & SVF_MONSTER) && !other->client )
return;
// trigger the prox mine if it's still there, and still mine.
prox = ent->owner;
@ -359,8 +363,8 @@ void Prox_Field_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t
if (prox->think == Prox_Explode) // we're set to blow!
{
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("%f - prox already gone off!\n", level.time);
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("%f - prox already gone off!\n", level.time);
return;
}
@ -415,16 +419,17 @@ void prox_open (edict_t *ent)
// doesn't get stuck on it while it's opening if fired at point blank wall
ent->s.sound = 0;
// Knightmare- the above never happens, and the owner pointer is needed for remote detonation
//ent->owner = NULL;
// ent->owner = NULL;
if (ent->teamchain)
ent->teamchain->touch = Prox_Field_Touch;
while ((search = findradius(search, ent->s.origin, sk_prox_radius->value + 10)) != NULL)
// while ((search = findradius(search, ent->s.origin, sk_prox_radius->value + 10)) != NULL)
while ((search = findradius(search, ent->s.origin, ent->dmg_radius + 10)) != NULL)
{
if (!search->classname) // tag token and other weird shit
continue;
// if (!search->takedamage)
// continue;
// if (!search->takedamage)
// continue;
// if it's a monster or player with health > 0
// or it's a player start point
// and we can see it
@ -452,27 +457,28 @@ void prox_open (edict_t *ent)
}
if (strong_mines && (strong_mines->value))
ent->wait = level.time + sk_prox_life->value;
ent->wait = level.time + ent->delay; // sk_prox_life->value // Knightmare- use stored timer
else
{
switch (ent->dmg / (int)sk_prox_damage->value)
// switch (ent->dmg / (int)sk_prox_damage->value)
switch (ent->count) // Knightmare- use stored multiplier
{
case 1:
ent->wait = level.time + sk_prox_life->value;
ent->wait = level.time + ent->delay; // sk_prox_life->value // Knightmare- use stored timer
break;
case 2:
ent->wait = level.time + sk_prox_life->value / 2;
ent->wait = level.time + ent->delay / 2; // sk_prox_life->value // Knightmare- use stored timer
break;
case 4:
ent->wait = level.time + sk_prox_life->value / 4;
ent->wait = level.time + ent->delay / 4; // sk_prox_life->value // Knightmare- use stored timer
break;
case 8:
ent->wait = level.time + sk_prox_life->value / 8;
ent->wait = level.time + ent->delay / 8; // sk_prox_life->value // Knightmare- use stored timer
break;
default:
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("prox with unknown multiplier %d!\n", ent->dmg/PROX_DAMAGE);
ent->wait = level.time + sk_prox_life->value;
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("prox with unknown multiplier %d!\n", ent->count);
ent->wait = level.time + ent->delay; // sk_prox_life->value // Knightmare- use stored timer
break;
}
}
@ -515,6 +521,7 @@ void prox_land (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
if (surf && (surf->flags & SURF_SKY))
{
Grenade_Remove_From_Chain (ent);
G_FreeEdict(ent);
return;
}
@ -550,8 +557,8 @@ void prox_land (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
if (!plane || !plane->normal) // this happens if you hit a point object, maybe other cases
{
// Since we can't tell what's going to happen, just blow up
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("bad normal for surface, exploding!\n");
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("bad normal for surface, exploding!\n");
Prox_Explode(ent);
return;
@ -605,8 +612,8 @@ void prox_land (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
if (plane->normal[2] > 0.7)
{
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("stuck on entity, blowing up!\n");
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("stuck on entity, blowing up!\n");
Prox_Explode(ent);
return;
@ -655,7 +662,8 @@ void prox_land (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
ent->movetype = movetype; // either bounce or none, depending on whether we stuck to something
ent->die = prox_die;
ent->teamchain = field;
ent->health = sk_prox_health->value;
// ent->health = sk_prox_health->value;
ent->health = ent->max_health; // Knightmare- health is stored in max_health
ent->nextthink = level.time + 0.05;
ent->think = prox_open;
ent->touch = NULL;
@ -672,7 +680,7 @@ void prox_land (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
//===============
//===============
void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage_multiplier, int speed)
void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int damage_multiplier, int speed, int health, float timer, float damage_radius)
{
edict_t *prox;
vec3_t dir;
@ -688,20 +696,20 @@ void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage_multiplie
VectorScale (aimdir, speed, prox->velocity);
VectorMA (prox->velocity, 200 + crandom() * 10.0, up, prox->velocity);
VectorMA (prox->velocity, crandom() * 10.0, right, prox->velocity);
//Knightmare- add player's base velocity to prox
// Knightmare- add player's base velocity to prox
if (add_velocity_throw->value && self->client)
VectorAdd (prox->velocity, self->velocity, prox->velocity);
else if (self->groundentity)
VectorAdd (prox->velocity, self->groundentity->velocity, prox->velocity);
VectorCopy (dir, prox->s.angles);
prox->s.angles[PITCH]-=90;
prox->s.angles[PITCH] -= 90;
prox->movetype = MOVETYPE_BOUNCE;
prox->solid = SOLID_BBOX;
prox->s.effects |= EF_GRENADE;
prox->clipmask = MASK_SHOT|CONTENTS_LAVA|CONTENTS_SLIME;
prox->s.renderfx |= RF_IR_VISIBLE;
//FIXME - this needs to be bigger. Has other effects, though. Maybe have to change origin to compensate
// FIXME - this needs to be bigger. Has other effects, though. Maybe have to change origin to compensate
// so it sinks in correctly. Also in lavacheck, might have to up the distance
VectorSet (prox->mins, -6, -6, -6);
VectorSet (prox->maxs, 6, 6, 6);
@ -709,34 +717,22 @@ void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage_multiplie
prox->owner = self;
prox->teammaster = self;
prox->touch = prox_land;
// prox->nextthink = level.time + sk_prox_life->value;
prox->nextthink = level.time + timer;
prox->think = Prox_Explode;
prox->dmg = sk_prox_damage->value*damage_multiplier;
// prox->dmg = sk_prox_damage->value * damage_multiplier;
prox->dmg = damage * damage_multiplier; // Knightmare- use damage param
prox->count = damage_multiplier; // Knightmare- store damage_multiplier param
prox->dmg_radius = damage_radius; // Knightmare- use damage_radius param
prox->max_health = health; // Knightmare- use health param
prox->delay = timer; // Knightmare- store timer param
prox->classname = "prox";
prox->class_id = ENTITY_MINE_PROX;
prox->svflags |= SVF_DAMAGEABLE;
prox->flags |= FL_MECHANICAL;
switch (damage_multiplier)
{
case 1:
prox->nextthink = level.time + sk_prox_life->value;
break;
case 2:
prox->nextthink = level.time + sk_prox_life->value;
break;
case 4:
prox->nextthink = level.time + sk_prox_life->value;
break;
case 8:
prox->nextthink = level.time + sk_prox_life->value;
break;
default:
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("prox with unknown multiplier %d!\n", damage_multiplier);
prox->nextthink = level.time + sk_prox_life->value;
break;
}
// Knightmare- mark monster-fired prox mines for avoidance
if (self->svflags & SVF_MONSTER)
Grenade_Add_To_Chain (prox);
gi.linkentity (prox);
}
@ -764,7 +760,7 @@ void prox_delayed_start (edict_t *prox)
{
VectorScale(prox->movedir,prox->moveinfo.speed,prox->velocity);
prox->movetype = MOVETYPE_BOUNCE;
prox->nextthink = level.time + sk_prox_life->value;
prox->nextthink = level.time + prox->delay; // sk_prox_life->value // Knightmare- use stored timer
prox->think = Prox_Explode;
gi.linkentity(prox);
}
@ -794,7 +790,7 @@ void SP_prox (edict_t *prox)
else
{
prox->movetype = MOVETYPE_BOUNCE;
prox->nextthink = level.time + sk_prox_life->value;
prox->nextthink = level.time + prox->delay; // sk_prox_life->value // Knightmare- use stored timer
prox->think = Prox_Explode;
}
gi.linkentity (prox);
@ -2269,7 +2265,7 @@ void fire_tesla (edict_t *self, vec3_t start, vec3_t aimdir, int damage_multipli
VectorScale (aimdir, speed, tesla->velocity);
VectorMA (tesla->velocity, 200 + crandom() * 10.0, up, tesla->velocity);
VectorMA (tesla->velocity, crandom() * 10.0, right, tesla->velocity);
//Knightmare- add player's base velocity to thrown tesla
// Knightmare- add player's base velocity to thrown tesla
if (add_velocity_throw->value && self->client)
VectorAdd (tesla->velocity, self->velocity, tesla->velocity);
else if (self->groundentity)

View file

@ -586,6 +586,9 @@ spawn_t spawns[] = {
{"misc_seat", SP_misc_seat},
// end Zaero
// Knightmare- added Gunner Commander
{"monster_gunner_commander", SP_monster_gunner},
// Knightmare- the dog from Coconut Monkey 3
{"monster_dog", SP_monster_dog},
// Knightmare- the vulture from Coconut Monkey 2
@ -881,6 +884,9 @@ void ED_CallSpawn (edict_t *ent)
// don't spawn another medic commander from medic commander
&& !(ent->monsterinfo.monsterflags & MFL_DO_NOT_COUNT))
ent->classname = "monster_medic_commander";
// gunner
if ( !strcmp(ent->classname, "monster_gunner") && (random() < ((skill->value + 1.0f) * 0.15f)) )
ent->classname = "monster_gunner_commander";
}
// LM Escape monster replacement

View file

@ -146,15 +146,15 @@ void thing_think_pause (edict_t *self)
vec3_t dir;
vec3_t angles;
if (visible(monster->enemy,monster))
if (visible(monster->enemy, monster))
{
self->touch_debounce_time = 0;
thing_think(self);
return;
}
VectorSubtract(monster->enemy->s.origin,monster->s.origin,dir);
VectorNormalize(dir);
vectoangles(dir,angles);
VectorSubtract (monster->enemy->s.origin, monster->s.origin, dir);
VectorNormalize (dir);
vectoangles (dir, angles);
monster->ideal_yaw = angles[YAW];
M_ChangeYaw(monster);
}
@ -212,7 +212,8 @@ void thing_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *su
// make sure this is still a grenade
if (grenade->inuse)
{
if (Q_stricmp(grenade->classname,"grenade") && Q_stricmp(grenade->classname,"hgrenade"))
if (Q_stricmp(grenade->classname, "grenade") && Q_stricmp(grenade->classname, "hgrenade")
&& Q_stricmp(grenade->classname, "prox")) // Knightmare- added prox
other->next_grenade = grenade = NULL;
}
else

View file

@ -541,7 +541,7 @@ void Grenade_Evade (edict_t *monster)
// if it ain't in the PVS, it can't hurt us (I think?)
if (gi.inPVS(grenade->s.origin,monster->s.origin))
{
VectorSubtract(grenade->s.origin,monster->s.origin,grenade_vec);
VectorSubtract (grenade->s.origin, monster->s.origin, grenade_vec);
grenade_dist = VectorNormalize(grenade_vec);
if (grenade_dist <= grenade->dmg_radius)
break;
@ -560,16 +560,16 @@ void Grenade_Evade (edict_t *monster)
forward[1] = sin( DEG2RAD(yaw) );
forward[2] = 0;
// Estimate of required distance to run. This is conservative.
r = grenade->dmg_radius + grenade_dist*DotProduct(forward,grenade_vec) + monster->size[0] + 16;
r = grenade->dmg_radius + grenade_dist*DotProduct(forward, grenade_vec) + monster->size[0] + 16;
if ( r < best_r )
{
VectorMA(monster->s.origin,r,forward,pos);
tr = gi.trace(monster->s.origin,monster->mins,monster->maxs,pos,monster,MASK_MONSTERSOLID);
VectorMA (monster->s.origin, r, forward,pos);
tr = gi.trace(monster->s.origin, monster->mins, monster->maxs, pos, monster, MASK_MONSTERSOLID);
if (tr.fraction < 1.0)
continue;
best_r = r;
best_yaw = yaw;
VectorCopy(tr.endpos,best_pos);
VectorCopy (tr.endpos, best_pos);
}
}
if (best_r < 9000)
@ -588,7 +588,7 @@ void Grenade_Evade (edict_t *monster)
}
}
/*static*/ void Grenade_Add_To_Chain (edict_t *grenade)
void Grenade_Add_To_Chain (edict_t *grenade)
{
edict_t *ancestor;
@ -599,7 +599,7 @@ void Grenade_Evade (edict_t *monster)
grenade->prev_grenade = ancestor;
}
/*static*/ void Grenade_Remove_From_Chain (edict_t *grenade)
void Grenade_Remove_From_Chain (edict_t *grenade)
{
if (grenade->prev_grenade)
{
@ -617,10 +617,12 @@ void Grenade_Explode (edict_t *ent)
int mod;
int type; // Knightmare added
Grenade_Remove_From_Chain (ent);
if (ent->owner->client)
PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT);
//FIXME: if we are onground then raise our Z just a bit since we are a point?
// FIXME: if we are onground then raise our Z just a bit since we are a point?
if (ent->enemy)
{
float points;
@ -674,13 +676,14 @@ void Grenade_Explode (edict_t *ent)
G_FreeEdict (ent);
}
/*static*/ void Grenade_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
void Grenade_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
if (other == ent->owner)
return;
if (surf && (surf->flags & SURF_SKY))
{
Grenade_Remove_From_Chain (ent);
G_FreeEdict (ent);
return;
}
@ -705,7 +708,7 @@ void Grenade_Explode (edict_t *ent)
Grenade_Explode (ent);
}
/*static*/ void ContactGrenade_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
void ContactGrenade_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
if (other == ent->owner)
return;
@ -764,6 +767,8 @@ void fire_grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int s
grenade->classname = "grenade";
grenade->class_id = ENTITY_GRENADE;
Grenade_Add_To_Chain (grenade);
gi.linkentity (grenade);
}
@ -781,7 +786,7 @@ void fire_grenade2 (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int
VectorScale (aimdir, speed, grenade->velocity);
VectorMA (grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity);
VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity);
//Knightmare- add player's base velocity to thrown grenade
// Knightmare- add player's base velocity to thrown grenade
if (add_velocity_throw->value && self->client)
VectorAdd (grenade->velocity, self->velocity, grenade->velocity);
else if (self->groundentity)
@ -815,6 +820,7 @@ void fire_grenade2 (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int
else
{
gi.sound (self, CHAN_WEAPON, gi.soundindex ("weapons/hgrent1a.wav"), 1, ATTN_NORM, 0);
Grenade_Add_To_Chain (grenade);
gi.linkentity (grenade);
}
}
@ -922,71 +928,71 @@ qboolean AimGrenade (edict_t *self, vec3_t start, vec3_t target, vec_t speed, ve
int i;
vec3_t last_aim;
VectorCopy(target,aim_point);
VectorSubtract(aim_point,self->s.origin,from_origin);
VectorSubtract(aim_point, start, from_muzzle);
VectorCopy (target, aim_point);
VectorSubtract (aim_point, self->s.origin,from_origin);
VectorSubtract (aim_point, start, from_muzzle);
if(self->svflags & SVF_MONSTER)
if (self->svflags & SVF_MONSTER)
{
VectorCopy(from_muzzle,aim);
VectorNormalize(aim);
VectorCopy (from_muzzle, aim);
VectorNormalize (aim);
yo = from_muzzle[2];
xo = sqrt(from_muzzle[0]*from_muzzle[0] + from_muzzle[1]*from_muzzle[1]);
xo = sqrt (from_muzzle[0] * from_muzzle[0] + from_muzzle[1] * from_muzzle[1]);
}
else
{
VectorCopy(from_origin,aim);
VectorNormalize(aim);
VectorCopy (from_origin, aim);
VectorNormalize (aim);
yo = from_origin[2];
xo = sqrt(from_origin[0]*from_origin[0] + from_origin[1]*from_origin[1]);
xo = sqrt (from_origin[0] * from_origin[0] + from_origin[1] * from_origin[1]);
}
// If resulting aim vector is looking straight up or straight down, we're
// done. Actually now that I write this down and think about it... should
// probably check straight up to make sure grenade will actually reach the
// target.
if( (aim[2] == 1.0) || (aim[2] == -1.0))
if ( (aim[2] == 1.0) || (aim[2] == -1.0))
return true;
// horizontal distance to target from muzzle
x = sqrt( from_muzzle[0]*from_muzzle[0] + from_muzzle[1]*from_muzzle[1]);
cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]);
x = sqrt (from_muzzle[0] * from_muzzle[0] + from_muzzle[1] * from_muzzle[1]);
cosa = sqrt (aim[0] * aim[0] + aim[1] * aim[1]);
// constant horizontal velocity (since grenades don't have drag)
vx = speed * cosa;
// time to reach target x
t = x/vx;
t = x / vx;
// if flight time is less than one frame, no way grenade will drop much,
// shoot the sucker now.
if(t < FRAMETIME)
if (t < FRAMETIME)
return true;
// in that time, grenade will drop this much:
drop = 0.5*sv_gravity->value*t*t;
drop = 0.5 * sv_gravity->value * t * t;
y = speed*aim[2]*t - drop;
v_error = target[2] - start[2] - y;
// if we're fairly close and we'll hit target at current angle,
// no need for all this, just shoot it
if( (x < 128) && (fabs(v_error) < 16) )
if ( (x < 128) && (fabs(v_error) < 16) )
return true;
last_error = 100000.;
VectorCopy(aim,last_aim);
VectorCopy (aim, last_aim);
// Unfortunately there is no closed-form solution for this problem,
// so we creep up on an answer and balk if it takes more than
// 10 iterations to converge to the tolerance we'll accept.
for(i=0; i<10 && fabs(v_error) > 4 && fabs(v_error) < fabs(last_error); i++)
for (i=0; i<10 && fabs(v_error) > 4 && fabs(v_error) < fabs(last_error); i++)
{
last_error = v_error;
aim[2] = cosa * (yo + drop)/xo;
VectorNormalize(aim);
if(!(self->svflags & SVF_MONSTER))
VectorNormalize (aim);
if (!(self->svflags & SVF_MONSTER))
{
vectoangles(aim,angles);
AngleVectors(angles, forward, right, up);
G_ProjectSource2(self->s.origin,self->move_origin,forward,right,up,start);
VectorSubtract(aim_point,start,from_muzzle);
x = sqrt(from_muzzle[0]*from_muzzle[0] + from_muzzle[1]*from_muzzle[1]);
vectoangles (aim ,angles);
AngleVectors (angles, forward, right, up);
G_ProjectSource2 (self->s.origin, self->move_origin, forward, right, up, start);
VectorSubtract (aim_point, start, from_muzzle);
x = sqrt(from_muzzle[0] * from_muzzle[0] + from_muzzle[1] * from_muzzle[1]);
}
cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]);
vx = speed * cosa;
@ -994,21 +1000,22 @@ qboolean AimGrenade (edict_t *self, vec3_t start, vec3_t target, vec_t speed, ve
drop = 0.5*sv_gravity->value*t*t;
y = speed*aim[2]*t - drop;
v_error = target[2] - start[2] - y;
if(fabs(v_error) < fabs(last_error))
if (fabs(v_error) < fabs(last_error))
VectorCopy(aim,last_aim);
}
if(i >= 10 || v_error > 64)
if (i >= 10 || v_error > 64)
return false;
if(fabs(v_error) > fabs(last_error))
if (fabs(v_error) > fabs(last_error))
{
VectorCopy(last_aim,aim);
if(!(self->svflags & SVF_MONSTER))
if (!(self->svflags & SVF_MONSTER))
{
vectoangles(aim,angles);
AngleVectors(angles, forward, right, up);
G_ProjectSource2(self->s.origin,self->move_origin,forward,right,up,start);
VectorSubtract(aim_point,start,from_muzzle);
vectoangles (aim, angles);
AngleVectors (angles, forward, right, up);
G_ProjectSource2 (self->s.origin, self->move_origin, forward,right, up, start);
VectorSubtract (aim_point, start, from_muzzle);
}
}
@ -1017,49 +1024,52 @@ qboolean AimGrenade (edict_t *self, vec3_t start, vec3_t target, vec_t speed, ve
// top of a doorway or other obstruction. If he WOULD do that, then figure out
// the max elevation angle that will get the grenade through the door, and
// hope we get a good bounce.
if( (start[2] - target[2] < 160) &&
if ( (start[2] - target[2] < 160) &&
(start[2] - target[2] > -16) )
{
trace_t tr;
vec3_t dist;
tr = gi.trace(start,vec3_origin,vec3_origin,aim_point,self,MASK_SOLID);
if( (tr.fraction < 1.0) && (!self->enemy || (tr.ent != self->enemy) )) {
tr = gi.trace(start, vec3_origin, vec3_origin, aim_point, self, MASK_SOLID);
if ( (tr.fraction < 1.0) && (!self->enemy || (tr.ent != self->enemy) ))
{
// OK... the aim vector hit a solid, but would the grenade actually hit?
int contents;
cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]);
cosa = sqrt(aim[0] * aim[0] + aim[1] * aim[1]);
vx = speed * cosa;
VectorSubtract(tr.endpos,start,dist);
VectorSubtract (tr.endpos, start, dist);
dist[2] = 0;
x = VectorLength(dist);
x = VectorLength (dist);
t = x/vx;
drop = 0.5*sv_gravity->value*t*(t+FRAMETIME);
drop = 0.5 * sv_gravity->value * t * (t + FRAMETIME);
tr.endpos[2] -= drop;
// move just a bit in the aim direction
tr.endpos[0] += aim[0];
tr.endpos[1] += aim[1];
contents = gi.pointcontents(tr.endpos);
while((contents & MASK_SOLID) && (aim_point[2] > target[2])) {
while ((contents & MASK_SOLID) && (aim_point[2] > target[2]))
{
aim_point[2] -= 8.0;
VectorSubtract(aim_point,self->s.origin,from_origin);
VectorCopy(from_origin,aim);
VectorNormalize(aim);
if(!(self->svflags & SVF_MONSTER))
VectorSubtract (aim_point, self->s.origin, from_origin);
VectorCopy (from_origin, aim);
VectorNormalize (aim);
if (!(self->svflags & SVF_MONSTER))
{
vectoangles(aim,angles);
AngleVectors(angles, forward, right, up);
G_ProjectSource2(self->s.origin,self->move_origin,forward,right,up,start);
VectorSubtract(aim_point,start,from_muzzle);
vectoangles (aim, angles);
AngleVectors (angles, forward, right, up);
G_ProjectSource2 (self->s.origin, self->move_origin, forward, right, up, start);
VectorSubtract (aim_point, start, from_muzzle);
}
tr = gi.trace(start,vec3_origin,vec3_origin,aim_point,self,MASK_SOLID);
if(tr.fraction < 1.0) {
cosa = sqrt(aim[0]*aim[0] + aim[1]*aim[1]);
tr = gi.trace(start, vec3_origin, vec3_origin, aim_point, self,MASK_SOLID);
if (tr.fraction < 1.0)
{
cosa = sqrt(aim[0] * aim[0] + aim[1] * aim[1]);
vx = speed * cosa;
VectorSubtract(tr.endpos,start,dist);
VectorSubtract (tr.endpos, start, dist);
dist[2] = 0;
x = VectorLength(dist);
t = x/vx;
drop = 0.5*sv_gravity->value*t*(t+FRAMETIME);
drop = 0.5 * sv_gravity->value * t * (t + FRAMETIME);
tr.endpos[2] -= drop;
tr.endpos[0] += aim[0];
tr.endpos[1] += aim[1];

View file

@ -420,5 +420,7 @@ ENTITY_TARGET_Q1_TRAPSHOOTER,
ENTITY_MISC_Q1_EXPLOBOX,
ENTITY_Q1_FIREBALL,
ENTITY_MISC_Q1_FIREBALL_SPAWNER,
ENTITY_MONSTER_Q1_FREDDIE
ENTITY_MONSTER_Q1_FREDDIE,
// New stuff
ENTITY_MONSTER_GUNNER_COMMANDER
} entity_id;

View file

@ -1054,6 +1054,6 @@ void SP_monster_chick (edict_t *self)
*/
void SP_monster_chick_heat (edict_t *self)
{
self->spawnflags |= SF_MONSTER_SPECIAL; //Knightmare- homing rockets flag
self->spawnflags |= SF_MONSTER_SPECIAL; // Knightmare- homing rockets flag
SP_monster_chick (self);
}

View file

@ -487,14 +487,22 @@ void GunnerFire (edict_t *self)
if (!self->enemy || !self->enemy->inuse) //PGM
return; //PGM
flash_number = MZ2_GUNNER_MACHINEGUN_1 + (self->s.frame - FRAME_attak216);
#ifdef KMQUAKE2_ENGINE_MOD // Knightmare- unique muzzle flash for gunner commander's flechettes
if (self->moreflags & FL2_COMMANDER)
flash_number = MZ2_GUNNER_ETF_RIFLE_1 + (self->s.frame - FRAME_attak216);
else
#endif // KMQUAKE2_ENGINE_MOD
flash_number = MZ2_GUNNER_MACHINEGUN_1 + (self->s.frame - FRAME_attak216);
AngleVectors (self->s.angles, forward, right, NULL);
G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
// project enemy back a bit and target there
VectorCopy (self->enemy->s.origin, target);
VectorMA (target, -0.2, self->enemy->velocity, target);
if ( !(self->moreflags & FL2_COMMANDER) )
{ // Commander fires projectiles, so no backward projection
VectorMA (target, -0.2, self->enemy->velocity, target);
}
target[2] += self->enemy->viewheight;
// Lazarus fog reduction of accuracy
@ -507,24 +515,30 @@ void GunnerFire (edict_t *self)
VectorSubtract (target, start, aim);
VectorNormalize (aim);
monster_fire_bullet (self, start, aim, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
// Knightmare- gunner commander fires flechettes
if (self->moreflags & FL2_COMMANDER)
monster_fire_flechette (self, start, aim, 5, 850, 75, 10, flash_number);
else
monster_fire_bullet (self, start, aim, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
}
void GunnerGrenade (edict_t *self)
{
vec3_t start;
vec3_t forward, right, up;
vec3_t aim;
vec_t monster_speed;
int flash_number;
float spread;
// float pitch;
vec3_t start;
vec3_t forward, right, up;
vec3_t aim;
vec_t monster_speed;
int flash_number;
float spread;
// float pitch;
// PMM
vec3_t target;
qboolean blindfire;
vec3_t target;
qboolean blindfire = false;
if (!self->enemy || !self->enemy->inuse) //PGM
return; //PGM
//PGM
if (!self->enemy || !self->enemy->inuse)
return;
// pmm
if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
@ -554,21 +568,21 @@ void GunnerGrenade (edict_t *self)
// pmm
// if we're shooting blind and we still can't see our enemy
if ((blindfire) && (!visible(self, self->enemy)))
if ( (blindfire) && (!visible(self, self->enemy)) )
{
// and we have a valid blind_fire_target
if (VectorCompare (self->monsterinfo.blind_fire_target, vec3_origin))
return;
// gi.dprintf ("blind_fire_target = %s\n", vtos (self->monsterinfo.blind_fire_target));
// gi.dprintf ("GunnerGrenade: ideal yaw is %f\n", self->ideal_yaw);
// gi.dprintf ("blind_fire_target = %s\n", vtos (self->monsterinfo.blind_fire_target));
// gi.dprintf ("GunnerGrenade: ideal yaw is %f\n", self->ideal_yaw);
VectorCopy (self->monsterinfo.blind_fire_target, target);
}
else
VectorCopy (self->s.origin, target);
// pmm
AngleVectors (self->s.angles, forward, right, up); //PGM
AngleVectors (self->s.angles, forward, right, up); // PGM
G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
//PGM
@ -576,16 +590,33 @@ void GunnerGrenade (edict_t *self)
{
float dist;
// VectorSubtract(self->enemy->s.origin, self->s.origin, aim);
// VectorSubtract(self->enemy->s.origin, self->s.origin, aim);
VectorSubtract(target, self->s.origin, aim);
dist = VectorLength(aim);
// aim at enemy's feet if he's at same elevation or lower. otherwise aim at origin
VectorCopy(self->enemy->s.origin,target);
if (self->enemy->absmin[2] <= self->absmax[2]) target[2] = self->enemy->absmin[2];
// aim at enemy's feet if he's at same elevation or lower, otherwise aim at origin
VectorCopy (self->enemy->s.origin, target);
if (self->enemy->absmin[2] <= self->absmax[2])
target[2] = self->enemy->absmin[2];
// Knightmare- spread out Commander's prox mines so they don't collide
if (self->moreflags & FL2_COMMANDER)
{
if ( blindfire )
{
target[0] += crandom() * 192;
target[1] += crandom() * 192;
target[2] += crandom() * 192;
}
else
{
target[0] += crandom() * 32;
target[1] += crandom() * 32;
}
}
// Lazarus fog reduction of accuracy
if (self->monsterinfo.visibility < FOG_CANSEEGOOD)
if ( self->monsterinfo.visibility < FOG_CANSEEGOOD )
{
target[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
target[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
@ -598,22 +629,22 @@ void GunnerGrenade (edict_t *self)
float dist;
float time;
VectorSubtract(target, start, aim);
VectorSubtract (target, start, aim);
dist = VectorLength (aim);
time = dist/GRENADE_VELOCITY; // Not correct, but better than nothin'
VectorMA(target, time, self->enemy->velocity, target);
VectorMA (target, time, self->enemy->velocity, target);
}
// aim up if they're on the same level as me and far away.
if ((dist > 512) && (aim[2] < 64) && (aim[2] > -64))
aim[2] += (dist - 512);
/* VectorNormalize (aim);
/* VectorNormalize (aim);
pitch = aim[2];
if (pitch > 0.4)
pitch = 0.4;
else if (pitch < -0.5)
pitch = -0.5;*/
pitch = -0.5; */
}
//PGM
@ -626,18 +657,25 @@ void GunnerGrenade (edict_t *self)
vec3_t v1;
vec_t delta;
VectorCopy(self->velocity,v1);
VectorNormalize(v1);
delta = -monster_speed/GRENADE_VELOCITY;
VectorMA(aim,delta,v1,aim);
VectorNormalize(aim);
VectorCopy (self->velocity,v1);
VectorNormalize (v1);
delta = -monster_speed / GRENADE_VELOCITY;
VectorMA (aim,delta,v1,aim);
VectorNormalize (aim);
}
//FIXME : do a spread -225 -75 75 225 degrees around forward
// FIXME : do a spread -225 -75 75 225 degrees around forward
// VectorCopy (forward, aim);
// VectorMA (forward, spread, right, aim);
// VectorMA (aim, pitch, up, aim);
monster_fire_grenade (self, start, aim, 50, 600, flash_number);
// Knightmare- Gunner Commander fires prox mines
if (self->moreflags & FL2_COMMANDER)
{
float prox_timer = (blindfire) ? 60.0f : 2.5f;
monster_fire_prox (self, start, aim, 65, 1, 600, 20, prox_timer, 192, flash_number);
}
else
monster_fire_grenade (self, start, aim, 50, 600, flash_number);
}
mframe_t gunner_frames_attack_chain [] =
@ -696,8 +734,8 @@ void gunner_blind_check (edict_t *self)
VectorSubtract(self->monsterinfo.blind_fire_target, self->s.origin, aim);
self->ideal_yaw = vectoyaw(aim);
// gi.dprintf ("blind_fire_target = %s\n", vtos (self->monsterinfo.blind_fire_target));
// gi.dprintf ("gunner_attack: ideal yaw is %f\n", self->ideal_yaw);
// gi.dprintf ("blind_fire_target = %s\n", vtos (self->monsterinfo.blind_fire_target));
// gi.dprintf ("gunner_attack: ideal yaw is %f\n", self->ideal_yaw);
}
}
@ -756,13 +794,13 @@ void gunner_attack(edict_t *self)
// don't shoot if the dice say not to
if (r > chance)
{
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("blindfire - NO SHOT\n");
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("blindfire - NO SHOT\n");
return;
}
// turn on manual steering to signal both manual steering and blindfire
//self->monsterinfo.aiflags |= AI_MANUAL_STEERING;
// self->monsterinfo.aiflags |= AI_MANUAL_STEERING;
self->monsterinfo.monsterflags |= AI_MANUAL_STEERING;
if (gunner_grenade_check(self))
{
@ -771,10 +809,10 @@ void gunner_attack(edict_t *self)
self->monsterinfo.attack_finished = level.time + 2*random();
}
// pmm - should this be active?
// else
// self->monsterinfo.currentmove = &gunner_move_attack_chain;
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("blind grenade check failed, doing nothing\n");
// else
// self->monsterinfo.currentmove = &gunner_move_attack_chain;
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("blind grenade check failed, doing nothing\n");
// turn off blindfire flag
self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
@ -1069,6 +1107,8 @@ void gunner_sidestep (edict_t *self)
/*QUAKED monster_gunner (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight GoodGuy NoGib
*/
/*QUAKED monster_gunner_commander (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight GoodGuy NoGib
*/
void SP_monster_gunner (edict_t *self)
{
if (deathmatch->value)
@ -1085,17 +1125,22 @@ void SP_monster_gunner (edict_t *self)
sound_search = gi.soundindex ("gunner/gunsrch1.wav");
sound_sight = gi.soundindex ("gunner/sight1.wav");
gi.soundindex ("gunner/gunatck2.wav");
// gi.soundindex ("gunner/gunatck2.wav"); // not used by Gunner Commander
gi.soundindex ("gunner/gunatck3.wav");
self->movetype = MOVETYPE_STEP;
self->solid = SOLID_BBOX;
// Lazarus: special purpose skins
if (strcmp(self->classname, "monster_gunner_commander") == 0)
{
self->s.skinnum = 2;
self->moreflags |= FL2_COMMANDER;
}
if ( self->style )
{
PatchMonsterModel("models/monsters/gunner/tris.md2");
self->s.skinnum = self->style * 2;
self->s.skinnum += self->style * 4;
}
self->s.modelindex = gi.modelindex ("models/monsters/gunner/tris.md2");
@ -1109,12 +1154,40 @@ void SP_monster_gunner (edict_t *self)
VectorSet (self->mins, -16, -16, -24);
VectorSet (self->maxs, 16, 16, 32);
if (!self->health)
self->health = 175;
if (!self->gib_health)
self->gib_health = -150;
if (!self->mass)
self->mass = 200;
if (strcmp(self->classname, "monster_gunner_commander") == 0)
{ // precache
gi.modelindex ("models/weapons/g_prox/tris.md2");
gi.modelindex ("models/proj/flechette/tris.md2");
gi.soundindex ("weapons/nail1.wav");
if (!self->health)
self->health = 400;
if (!self->gib_health)
self->gib_health = -150;
if (!self->mass)
self->mass = 300;
self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD;
self->monsterinfo.power_armor_power = 200;
self->common_name = "Gunner Commander";
self->class_id = ENTITY_MONSTER_GUNNER_COMMANDER;
}
else
{ // precache
gi.modelindex ("models/objects/grenade/tris.md2");
gi.soundindex ("gunner/gunatck2.wav");
if (!self->health)
self->health = 175;
if (!self->gib_health)
self->gib_health = -150;
if (!self->mass)
self->mass = 200;
self->common_name = "Gunner";
self->class_id = ENTITY_MONSTER_GUNNER;
}
self->pain = gunner_pain;
self->die = gunner_die;
@ -1147,11 +1220,11 @@ void SP_monster_gunner (edict_t *self)
self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD;
self->monsterinfo.power_armor_power = self->powerarmor;
}
if (!self->monsterinfo.flies)
self->monsterinfo.flies = 0.30;
self->common_name = "Gunner";
self->class_id = ENTITY_MONSTER_GUNNER;
if ( !self->monsterinfo.flies && strcmp(self->classname, "monster_gunner_commander") == 0 )
self->monsterinfo.flies = 0.20;
else if (!self->monsterinfo.flies)
self->monsterinfo.flies = 0.30;
gi.linkentity (self);

View file

@ -33,7 +33,8 @@ static int daed_sound_search2;
void hover_sight (edict_t *self, edict_t *other)
{
// PMM - daedalus sounds
if (strcmp(self->classname, "monster_daedalus"))
// if (strcmp(self->classname, "monster_daedalus"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_VOICE, daed_sound_sight, 1, ATTN_NORM, 0);
@ -42,7 +43,8 @@ void hover_sight (edict_t *self, edict_t *other)
void hover_search (edict_t *self)
{
// PMM - daedalus sounds
if (strcmp(self->classname, "monster_daedalus"))
// if (strcmp(self->classname, "monster_daedalus"))
if ( !(self->moreflags & FL2_COMMANDER) )
{
if (random() < 0.5)
gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0);
@ -486,7 +488,7 @@ void hover_fire_blaster (edict_t *self)
vec3_t dir;
int effect;
if(!self->enemy || !self->enemy->inuse) //PGM
if (!self->enemy || !self->enemy->inuse) //PGM
return; //PGM
if (self->s.frame == FRAME_attak104)
@ -501,7 +503,7 @@ void hover_fire_blaster (edict_t *self)
end[2] += self->enemy->viewheight;
// Lazarus fog reduction of accuracy
if(self->monsterinfo.visibility < FOG_CANSEEGOOD)
if (self->monsterinfo.visibility < FOG_CANSEEGOOD)
{
end[0] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
end[1] += crandom() * 640 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
@ -510,7 +512,8 @@ void hover_fire_blaster (edict_t *self)
VectorSubtract (end, start, dir);
//PGM - daedalus fires blaster2
if (strcmp(self->classname, "monster_daedalus") == 0)
// if (strcmp(self->classname, "monster_daedalus") == 0)
if (self->moreflags & FL2_COMMANDER)
// monster_fire_blaster (self, start, dir, self->dmg, 1000, MZ2_DAEDALUS_BLASTER, EF_BLASTER|EF_TRACKER, BLASTER_GREEN);
monster_fire_blaster2 (self, start, dir, self->dmg, 1000, MZ2_DAEDALUS_BLASTER, EF_BLASTER);
// fixme - different muzzle flash
@ -558,7 +561,8 @@ void hover_attack(edict_t *self)
else
chance = 1.0 - (0.5/(float)(skill->value));
if (strcmp(self->classname, "monster_daedalus") == 0)
// if (strcmp(self->classname, "monster_daedalus") == 0)
if (self->moreflags & FL2_COMMANDER)
chance += 0.1;
if (random() > chance)
@ -600,7 +604,8 @@ void hover_pain (edict_t *self, edict_t *other, float kick, int damage)
if (random() < 0.5)
{
// PMM - daedalus sounds
if (strcmp(self->classname, "monster_daedalus"))
// if (strcmp(self->classname, "monster_daedalus"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_VOICE, daed_sound_pain1, 1, ATTN_NORM, 0);
@ -609,7 +614,8 @@ void hover_pain (edict_t *self, edict_t *other, float kick, int damage)
else
{
// PMM - daedalus sounds
if (strcmp(self->classname, "monster_daedalus"))
// if (strcmp(self->classname, "monster_daedalus"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_VOICE, daed_sound_pain2, 1, ATTN_NORM, 0);
@ -623,7 +629,8 @@ void hover_pain (edict_t *self, edict_t *other, float kick, int damage)
if (random() < (0.45 - (0.1 * skill->value)))
{
// PMM - daedalus sounds
if (strcmp(self->classname, "monster_daedalus"))
// if (strcmp(self->classname, "monster_daedalus"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_VOICE, daed_sound_pain1, 1, ATTN_NORM, 0);
@ -632,7 +639,8 @@ void hover_pain (edict_t *self, edict_t *other, float kick, int damage)
else
{
// PMM - daedalus sounds
if (strcmp(self->classname, "monster_daedalus"))
// if (strcmp(self->classname, "monster_daedalus"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_VOICE, daed_sound_pain2, 1, ATTN_NORM, 0);
@ -714,7 +722,8 @@ void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage
// regular death
// PMM - daedalus sounds
if (strcmp(self->classname, "monster_daedalus"))
// if (strcmp(self->classname, "monster_daedalus"))
if ( !(self->moreflags & FL2_COMMANDER) )
{
if (random() < 0.5)
gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0);
@ -737,7 +746,7 @@ void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage
//PGM
qboolean hover_blocked (edict_t *self, float dist)
{
if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
if (blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
return true;
return false;
@ -763,7 +772,10 @@ void SP_monster_hover (edict_t *self)
// Lazarus: special purpose skins
if (strcmp(self->classname, "monster_daedalus") == 0)
{
self->s.skinnum = 2;
self->moreflags |= FL2_COMMANDER;
}
if ( self->style )
{
PatchMonsterModel("models/monsters/hover/tris.md2");
@ -772,7 +784,7 @@ void SP_monster_hover (edict_t *self)
self->s.modelindex = gi.modelindex("models/monsters/hover/tris.md2");
//Knightmare- smaller bounding box for Pierre replacement in Coconut Monkey level 3
// Knightmare- smaller bounding box for Pierre replacement in Coconut Monkey level 3
if (Q_stricmp(level.mapname, "cm3pt3") == 0
&& !strcmp(self->combattarget, "showdown"))
{
@ -785,7 +797,7 @@ void SP_monster_hover (edict_t *self)
VectorSet (self->maxs, 24, 24, 32);
}
if(!self->gib_health)
if (!self->gib_health)
self->gib_health = -100;
self->pain = hover_pain;
@ -806,15 +818,18 @@ void SP_monster_hover (edict_t *self)
//PGM
if (strcmp(self->classname, "monster_daedalus") == 0)
{
if(!self->health)
// self->s.skinnum = 2;
if (!self->health)
self->health = 450;
if(!self->mass)
if (!self->mass)
self->mass = 225;
self->yaw_speed = 25;
if (!self->dmg)
self->dmg = 2;
self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
self->monsterinfo.power_armor_power = 100;
// PMM - daedalus sounds
self->s.sound = gi.soundindex ("daedalus/daedidle1.wav");
daed_sound_pain1 = gi.soundindex ("daedalus/daedpain1.wav");
@ -828,14 +843,14 @@ void SP_monster_hover (edict_t *self)
// Knightmare- precache blaster bolt
gi.modelindex ("models/proj/laser2/tris.md2");
// pmm
self->common_name = "Daedalus"; // Knightmare
self->common_name = "Daedalus"; // Knightmare added
self->class_id = ENTITY_MONSTER_DAEDALUS;
}
else
{
if(!self->health)
if (!self->health)
self->health = 240;
if(!self->mass)
if (!self->mass)
self->mass = 150;
if (!self->dmg)
self->dmg = 1;
@ -849,13 +864,13 @@ void SP_monster_hover (edict_t *self)
gi.soundindex ("hover/hovatck1.wav");
self->s.sound = gi.soundindex ("hover/hovidle1.wav");
self->common_name = "Icarus"; // Knightmare
self->common_name = "Icarus"; // Knightmare added
self->class_id = ENTITY_MONSTER_HOVER;
}
//PGM
// Lazarus
if(self->powerarmor)
if (self->powerarmor)
{
if (self->powerarmortype == 1)
self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
@ -870,9 +885,4 @@ void SP_monster_hover (edict_t *self)
self->monsterinfo.scale = MODEL_SCALE;
flymonster_start (self);
//PGM
// if (strcmp(self->classname, "monster_daedalus") == 0)
// self->s.skinnum = 2;
//PGM
}

View file

@ -404,7 +404,8 @@ void medic_idle (edict_t *self)
if (!(self->spawnflags & SF_MONSTER_AMBUSH))
{
// PMM - commander sounds
if (strcmp(self->classname, "monster_medic_commander"))
// if (strcmp(self->classname, "monster_medic_commander"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0);
else
gi.sound (self, CHAN_VOICE, commander_sound_idle1, 1, ATTN_IDLE, 0);
@ -490,7 +491,8 @@ void medic_search (edict_t *self)
edict_t *ent;
// PMM - commander sounds
if (strcmp(self->classname, "monster_medic_commander"))
// if (strcmp(self->classname, "monster_medic_commander"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_IDLE, 0);
else
gi.sound (self, CHAN_VOICE, commander_sound_search, 1, ATTN_IDLE, 0);
@ -512,7 +514,8 @@ void medic_search (edict_t *self)
void medic_sight (edict_t *self, edict_t *other)
{
// PMM - commander sounds
if (strcmp(self->classname, "monster_medic_commander"))
// if (strcmp(self->classname, "monster_medic_commander"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_VOICE, commander_sound_sight, 1, ATTN_NORM, 0);
@ -743,7 +746,8 @@ void medic_pain (edict_t *self, edict_t *other, float kick, int damage)
if (self->monsterinfo.aiflags & AI_MEDIC)
return;
if (strcmp(self->classname, "monster_medic_commander") == 0)
// if (strcmp(self->classname, "monster_medic_commander") == 0)
if (self->moreflags & FL2_COMMANDER)
{
if (damage < 35)
{
@ -815,7 +819,8 @@ void medic_fire_blaster (edict_t *self)
damage = 3;
// medic commander shoots blaster2
if (strcmp(self->classname, "monster_medic_commander") == 0)
// if (strcmp(self->classname, "monster_medic_commander") == 0)
if (self->moreflags & FL2_COMMANDER)
// monster_fire_blaster (self, start, dir, damage, 1000, MZ2_MEDIC_BLASTER_2, (effect!=0)?(effect|EF_TRACKER):0, BLASTER_GREEN);
monster_fire_blaster2 (self, start, dir, damage, 1000, MZ2_MEDIC_BLASTER_2, effect);
else
@ -905,7 +910,8 @@ void medic_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage
// regular death
// PMM
if (strcmp(self->classname, "monster_medic_commander"))
// if (strcmp(self->classname, "monster_medic_commander"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_VOICE, commander_sound_die, 1, ATTN_NORM, 0);
@ -992,7 +998,8 @@ mmove_t medic_move_attackBlaster = {FRAME_attack1, FRAME_attack14, medic_frames_
void medic_hook_launch (edict_t *self)
{
// PMM - commander sounds
if (strcmp(self->classname, "monster_medic_commander"))
// if (strcmp(self->classname, "monster_medic_commander"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_WEAPON, sound_hook_launch, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_WEAPON, commander_sound_hook_launch, 1, ATTN_NORM, 0);
@ -1122,7 +1129,8 @@ void medic_cable_attack (edict_t *self)
if (self->s.frame == FRAME_attack43)
{
// PMM - commander sounds
if (strcmp(self->classname, "monster_medic_commander"))
// if (strcmp(self->classname, "monster_medic_commander"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0);
else
gi.sound (self->enemy, CHAN_AUTO, commander_sound_hook_hit, 1, ATTN_NORM, 0);
@ -1265,7 +1273,8 @@ void medic_cable_attack (edict_t *self)
{
if (self->s.frame == FRAME_attack44)
// PMM - medic commander sounds
if (strcmp(self->classname, "monster_medic_commander"))
// if (strcmp(self->classname, "monster_medic_commander"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_WEAPON, commander_sound_hook_heal, 1, ATTN_NORM, 0);
@ -1291,7 +1300,8 @@ void medic_cable_attack (edict_t *self)
void medic_hook_retract (edict_t *self)
{
if (strcmp(self->classname, "monster_medic_commander"))
// if (strcmp(self->classname, "monster_medic_commander"))
if ( !(self->moreflags & FL2_COMMANDER) )
gi.sound (self, CHAN_WEAPON, sound_hook_retract, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_WEAPON, sound_hook_retract, 1, ATTN_NORM, 0);
@ -1619,23 +1629,23 @@ void medic_finish_spawn (edict_t *self)
ent = CreateGroundMonster (spawnpoint, self->s.angles,
reinforcement_mins[summonStr-inc], reinforcement_maxs[summonStr-inc],
reinforcements[summonStr-inc], 256);
// else if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("CheckSpawnPoint failed volume check!\n");
// else if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("CheckSpawnPoint failed volume check!\n");
}
else
{
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("FindSpawnPoint failed to find a point!\n");
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("FindSpawnPoint failed to find a point!\n");
}
if (!ent)
{
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("Spawn point obstructed for %s, aborting!\n", reinforcements[summonStr-inc]);
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("Spawn point obstructed for %s, aborting!\n", reinforcements[summonStr-inc]);
continue;
}
// gi.sound (self, CHAN_WEAPON, commander_sound_spawn, 1, ATTN_NORM, 0);
// gi.sound (self, CHAN_WEAPON, commander_sound_spawn, 1, ATTN_NORM, 0);
if (ent->think)
{
@ -1648,8 +1658,8 @@ void medic_finish_spawn (edict_t *self)
ent->monsterinfo.monsterflags |= MFL_DO_NOT_COUNT|MFL_SPAWNED_MEDIC_C;
ent->monsterinfo.commander = self;
self->monsterinfo.monster_slots--;
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("medic_commander: %d slots remaining\n", self->monsterinfo.monster_slots);
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("medic_commander: %d slots remaining\n", self->monsterinfo.monster_slots);
if (self->monsterinfo.aiflags & AI_MEDIC)
designated_enemy = self->oldenemy;
@ -1667,27 +1677,27 @@ void medic_finish_spawn (edict_t *self)
designated_enemy = PickCoopTarget(ent);
if (designated_enemy)
{
// if ((g_showlogic) && (g_showlogic->value))
// {
// gi.dprintf ("PickCoopTarget returned a %s - ", designated_enemy->classname);
// if (designated_enemy->client)
// gi.dprintf ("with name %s\n", designated_enemy->client->pers.netname);
// else
// gi.dprintf ("NOT A CLIENT\n");
// }
/* if ((g_showlogic) && (g_showlogic->value))
{
gi.dprintf ("PickCoopTarget returned a %s - ", designated_enemy->classname);
if (designated_enemy->client)
gi.dprintf ("with name %s\n", designated_enemy->client->pers.netname);
else
gi.dprintf ("NOT A CLIENT\n");
} */
}
else
{
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("pick coop failed, using my current enemy\n");
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("pick coop failed, using my current enemy\n");
designated_enemy = self->enemy;
}
}
}
else
{
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("pick coop failed, using my current enemy\n");
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("pick coop failed, using my current enemy\n");
designated_enemy = self->enemy;
}
}
@ -1695,8 +1705,8 @@ void medic_finish_spawn (edict_t *self)
if ((designated_enemy) && (designated_enemy->inuse) && (designated_enemy->health > 0))
{
// fixme
// if ((g_showlogic) && (g_showlogic -> value))
// gi.dprintf ("setting enemy to %s\n", designated_enemy->classname);
// if ((g_showlogic) && (g_showlogic -> value))
// gi.dprintf ("setting enemy to %s\n", designated_enemy->classname);
ent->enemy = designated_enemy;
FoundTarget (ent);
}
@ -1705,16 +1715,16 @@ void medic_finish_spawn (edict_t *self)
ent->enemy = NULL;
ent->monsterinfo.stand (ent);
}
// ent->s.event = EV_PLAYER_TELEPORT;
// ent->s.event = EV_PLAYER_TELEPORT;
}
}
mframe_t medic_frames_callReinforcements [] =
{
// ROGUE - 33-36 now ai_charge
ai_charge, 2, NULL, //33
ai_charge, 3, NULL,
ai_charge, 5, NULL,
ai_charge, 2, NULL, //33
ai_charge, 3, NULL,
ai_charge, 5, NULL,
ai_charge, 4.4, NULL, //36
ai_charge, 4.7, NULL,
ai_charge, 5, NULL,
@ -1728,7 +1738,7 @@ mframe_t medic_frames_callReinforcements [] =
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, medic_determine_spawn, //48
ai_charge, 0, medic_spawngrows, //49
ai_charge, 0, medic_spawngrows, //49
ai_move, 0, NULL, //50
ai_move, 0, NULL, //51
ai_move, -15, medic_finish_spawn, //52
@ -1743,7 +1753,7 @@ mframe_t medic_frames_callReinforcements [] =
};
mmove_t medic_move_callReinforcements = {FRAME_attack33, FRAME_attack60, medic_frames_callReinforcements, medic_run};
void medic_attack(edict_t *self)
void medic_attack (edict_t *self)
{
int enemy_range;
float r;
@ -1762,7 +1772,8 @@ void medic_attack(edict_t *self)
r = random();
if (self->monsterinfo.aiflags & AI_MEDIC)
{
if ((strcmp(self->classname, "monster_medic_commander") == 0) && (r > 0.8) && (self->monsterinfo.monster_slots > 2))
// if ((strcmp(self->classname, "monster_medic_commander") == 0) && (r > 0.8) && (self->monsterinfo.monster_slots > 2))
if ((self->moreflags & FL2_COMMANDER) && (r > 0.8) && (self->monsterinfo.monster_slots > 2))
self->monsterinfo.currentmove = &medic_move_callReinforcements;
else
self->monsterinfo.currentmove = &medic_move_attackCable;
@ -1774,7 +1785,8 @@ void medic_attack(edict_t *self)
self->monsterinfo.currentmove = &medic_move_callReinforcements;
return;
}
if ((strcmp(self->classname, "monster_medic_commander") == 0) && (r > 0.2) && (enemy_range != RANGE_MELEE) && (self->monsterinfo.monster_slots > 2))
// if ((strcmp(self->classname, "monster_medic_commander") == 0) && (r > 0.2) && (enemy_range != RANGE_MELEE) && (self->monsterinfo.monster_slots > 2))
if ((self->moreflags & FL2_COMMANDER) && (r > 0.2) && (enemy_range != RANGE_MELEE) && (self->monsterinfo.monster_slots > 2))
self->monsterinfo.currentmove = &medic_move_callReinforcements;
else
self->monsterinfo.currentmove = &medic_move_attackBlaster;
@ -2050,7 +2062,10 @@ void SP_monster_medic (edict_t *self)
// Lazarus: special purpose skins
if (strcmp(self->classname, "monster_medic_commander") == 0)
{
self->s.skinnum = 2;
self->moreflags |= FL2_COMMANDER;
}
if ( self->style )
{
PatchMonsterModel("models/monsters/medic/tris.md2");
@ -2061,7 +2076,7 @@ void SP_monster_medic (edict_t *self)
VectorSet (self->mins, -24, -24, -24);
VectorSet (self->maxs, 24, 24, 32);
//PMM
//PMM
if (strcmp(self->classname, "monster_medic_commander") == 0)
{
if (!self->health)
@ -2070,16 +2085,16 @@ void SP_monster_medic (edict_t *self)
self->gib_health = -150;
if (!self->mass)
self->mass = 600;
//PMM
// PMM
self->monsterinfo.aiflags |= AI_IGNORE_SHOTS;
self->yaw_speed = 40; // default is 20
MedicCommanderCache();
MedicCommanderCache ();
// Knightmare- precache blaster bolt
gi.modelindex ("models/proj/laser2/tris.md2");
}
else
{
//PMM
//PMM
if (!self->health)
self->health = 300;
if (!self->gib_health)
@ -2121,7 +2136,8 @@ void SP_monster_medic (edict_t *self)
self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD;
self->monsterinfo.power_armor_power = self->powerarmor;
}
if (!self->monsterinfo.flies && strcmp(self->classname, "monster_medic_commander") == 0)
if ( !self->monsterinfo.flies && strcmp(self->classname, "monster_medic_commander") == 0 )
self->monsterinfo.flies = 0.10;
else if (!self->monsterinfo.flies)
self->monsterinfo.flies = 0.15;

View file

@ -1028,7 +1028,10 @@ void SP_monster_tank (edict_t *self)
// Lazarus: special purpose skins
if (strcmp(self->classname, "monster_tank_commander") == 0)
{
self->s.skinnum = 2;
self->moreflags |= FL2_COMMANDER;
}
if ( self->style )
{
PatchMonsterModel("models/monsters/tank/tris.md2");
@ -1058,7 +1061,8 @@ void SP_monster_tank (edict_t *self)
gi.soundindex ("tank/tnkatk2e.wav");
gi.soundindex ("tank/tnkatck3.wav");
if (strcmp(self->classname, "monster_tank_commander") == 0)
// if (strcmp(self->classname, "monster_tank_commander") == 0)
if (self->moreflags & FL2_COMMANDER)
{
if (!self->health)
self->health = 1000;

View file

@ -695,7 +695,8 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
message = "was pumped full of lead by an";
}
// Gunner
else if (!strcmp(attacker->classname, "monster_gunner"))
else if (!strcmp(attacker->classname, "monster_gunner")
|| !strcmp(attacker->classname, "monster_gunner_commander") )
{
if (mod == MOD_GRENADE) {
message = "was popped by a";
@ -705,6 +706,17 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker)
message = "was shredded by a";
message2 = "'s shrapnel";
}
else if (mod == MOD_PROX) {
message = "got too close to a";
message2 = "'s proximity mine";
}
else if (mod == MOD_ETF_RIFLE) {
message = "was perforated by a";
}
else if (mod == MOD_ETF_SPLASH) {
message = "was torn up by a";
message2 = "'s explosive flechettes";
}
else
message = "was machinegunned by a";
}

View file

@ -999,7 +999,7 @@ void weapon_grenade_fire (edict_t *ent, qboolean held)
fire_tesla (ent, start, forward, damage_multiplier, speed);
break;
default:
fire_prox (ent, start, forward, damage_multiplier, speed);
fire_prox (ent, start, forward, (int)sk_prox_damage->value, damage_multiplier, speed, (int)sk_prox_health->value, sk_prox_life->value, sk_prox_radius->value);
break;
}
// PGM
@ -1370,18 +1370,18 @@ void weapon_grenadelauncher_fire (edict_t *ent, qboolean altfire)
// fire_grenade (ent, start, forward, damage, 600, 2.5, radius);
// =====
// PGM
switch(ent->client->pers.weapon->tag)
switch (ent->client->pers.weapon->tag)
{
case AMMO_PROX:
fire_prox (ent, start, forward, multiplier, sk_prox_speed->value); //was damage_multiplier
fire_prox (ent, start, forward, damage, multiplier, (int)sk_prox_speed->value, (int)sk_prox_health->value, sk_prox_life->value, sk_prox_radius->value);
break;
default:
fire_grenade (ent, start, forward, damage, sk_grenade_speed->value, 2.5, radius, altfire);
fire_grenade (ent, start, forward, damage, (int)sk_grenade_speed->value, 2.5, radius, altfire);
break;
}
// PGM
// =====
//Knightmare- Gen cam code
// Knightmare- Gen cam code
// if (ent->client && ent->client->chasetoggle)
if (ent->client && ent->client->chaseactive)
{