super-coop/source/items.qc

1232 lines
28 KiB
Plaintext

// items.qc: items the player can pick up
string() Key1Name = {
switch(world.worldtype) {
case WORLD_MEDIEVAL:
return "silver key";
case WORLD_METAL:
return "silver runekey";
case WORLD_BASE:
return "silver keycard";
default:
return string_null;
}
};
string() Key2Name = {
switch(world.worldtype) {
case WORLD_MEDIEVAL:
return "gold key";
case WORLD_METAL:
return "gold runekey";
case WORLD_BASE:
return "gold keycard";
default:
return string_null;
}
};
/* ALL LIGHTS SHOULD BE 0 1 0 IN COLOR ALL OTHER ITEMS SHOULD
BE .8 .3 .4 IN COLOR */
void() SUB_regen = {
self.model = self.mdl; // restore original model
self.solid = SOLID_TRIGGER; // allow it to be touched again
sound(self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM); // play respawn sound
setorigin(self, self.origin);
};
/*QUAKED noclass(0 0 0) (-8 -8 -8) (8 8 8)
prints a warning message when spawned
*/
void() noclass = {
dprint("noclass spawned at", vtos(self.origin), "\n");
remove(self);
};
/*
============
PlaceItem
plants the object on the floor
============
*/
void() PlaceItem = {
float oldz;
self.mdl = self.model; // so it can be restored on respawn
self.flags = FL_ITEM; // make extra wide
self.solid = SOLID_TRIGGER;
self.movetype = MOVETYPE_TOSS;
self.velocity = VEC_ORIGIN;
self.origin_z = self.origin_z + 6;
oldz = self.origin_z;
if(!droptofloor()) {
dprint("Bonus item fell out of level at ", vtos(self.origin), "\n");
remove(self);
return;
}
};
/*
============
StartItem
Sets the clipping size and plants the object on the floor
============
*/
void() StartItem = {
self.nextthink = time + 0.2; // items start after other solids
self.think = PlaceItem;
};
/*
=========================================================================
HEALTH BOX
=========================================================================
*/
//
// T_Heal: add health to an entity, limiting health to max_health
// "ignore" will ignore max_health limit
//
float(entity e, float healamount, float ignore) T_Heal = {
if(e.health <= 0 || (!ignore && e.health >= other.max_health)) {
return 0;
}
healamount = ceil(healamount);
e.health = e.health + healamount;
if(!ignore && e.health >= other.max_health) {
e.health = other.max_health;
}
if(e.health > 250) {
e.health = 250;
}
return 1;
};
/*QUAKED item_health(.3 .3 1) (0 0 0) (32 32 32) rotten megahealth
Health box. Normally gives 25 points.
Rotten box heals 15 points,
Megahealth will add 100 health, then rot you down to your maximum health limit,
one point per second.
*/
void() item_health = {
self.touch = health_touch;
if(self.spawnflags & HEALTH_ROTTEN) {
precache_model("maps/b_bh10.bsp");
precache_sound("items/r_item1.wav");
setmodel(self, "maps/b_bh10.bsp");
self.noise = "items/r_item1.wav";
self.healamount = 15;
self.healtype = 0;
} else if(self.spawnflags & HEALTH_MEGA) {
precache_model("maps/b_bh100.bsp");
precache_sound("items/r_item2.wav");
setmodel(self, "maps/b_bh100.bsp");
self.noise = "items/r_item2.wav";
self.healamount = 100;
self.healtype = 2;
} else {
precache_model("maps/b_bh25.bsp");
precache_sound("items/health1.wav");
setmodel(self, "maps/b_bh25.bsp");
self.noise = "items/health1.wav";
self.healamount = 25;
self.healtype = 1;
}
setsize(self, VEC_ORIGIN, '32 32 56');
StartItem();
};
void() health_touch = {
float amount;
if(other.classname != "player") {
return;
}
if(self.healtype == 2) { // Megahealth? Ignore max_health...
if(other.health >= 250 || !T_Heal(other, self.healamount, TRUE)) {
return;
}
} else if(!T_Heal(other, self.healamount, FALSE)) {
return;
}
sprint(other, "You receive ", ftos(self.healamount), " health\n");
// health touch sound
sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
stuffcmd(other, "bf\n");
self.model = string_null;
self.solid = SOLID_NOT;
// Megahealth = rot down the player's super health
if(self.healtype == 2) {
other.items = other.items | IT_SUPERHEALTH;
self.nextthink = time + 5;
self.think = item_megahealth_rot;
self.owner = other;
} else {
if(deathmatch != 2) { // deathmatch 2 is the silly old rules
if(deathmatch) {
self.nextthink = time + 20;
}
self.think = SUB_regen;
}
}
activator = other;
SUB_UseTargets(); // fire all targets / killtargets
};
void() item_megahealth_rot = {
other = self.owner;
if(other.health > other.max_health) {
other.health = other.health - 1;
self.nextthink = time + 1;
return;
}
// it is possible for a player to die and respawn between rots, so don't
// just blindly subtract the flag off
other.items = other.items - (other.items & IT_SUPERHEALTH);
if(deathmatch == 1) { // deathmatch 2 is silly old rules
self.nextthink = time + 20;
self.think = SUB_regen;
}
};
/*
===============================================================================
ARMOR
===============================================================================
*/
void() armor_touch = {
float type, value, bit;
if(other.health <= 0 || other.classname != "player") {
return;
}
switch(self.classname) {
case "item_armor1":
type = 0.3;
value = 100;
bit = IT_ARMOR1;
break;
case "item_armor2":
type = 0.6;
value = 150;
bit = IT_ARMOR2;
break;
case "item_armorInv":
type = 0.8;
value = 200;
bit = IT_ARMOR3;
break;
}
if(other.armortype * other.armorvalue >= type * value) {
return;
}
other.armortype = type;
other.armorvalue = value;
other.items = other.items - (other.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + bit;
self.solid = SOLID_NOT;
self.model = string_null;
if(deathmatch == 1) {
self.nextthink = time + 20;
}
self.think = SUB_regen;
sprint(other, "You got armor\n");
// armor touch sound
sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
stuffcmd(other, "bf\n");
activator = other;
SUB_UseTargets(); // fire all targets / killtargets
};
/*QUAKED item_armor1(0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() item_armor1 = {
self.touch = armor_touch;
precache_model("progs/armor.mdl");
setmodel(self, "progs/armor.mdl");
self.skin = 0;
setsize(self, '-16 -16 0', '16 16 56');
StartItem();
};
/*QUAKED item_armor2(0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() item_armor2 = {
self.touch = armor_touch;
precache_model("progs/armor.mdl");
setmodel(self, "progs/armor.mdl");
self.skin = 1;
setsize(self, '-16 -16 0', '16 16 56');
StartItem();
};
/*QUAKED item_armorInv(0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() item_armorInv = {
self.touch = armor_touch;
precache_model("progs/armor.mdl");
setmodel(self, "progs/armor.mdl");
self.skin = 2;
setsize(self, '-16 -16 0', '16 16 56');
StartItem();
};
/*
===============================================================================
WEAPONS
===============================================================================
*/
void(entity e) bound_ammo = {
if(e.ammo_shells > AMMAX_SHELLS) {
e.ammo_shells = AMMAX_SHELLS;
}
if(e.ammo_nails > AMMAX_NAILS) {
e.ammo_nails = AMMAX_NAILS;
}
if(e.ammo_rockets > AMMAX_ROCKETS) {
e.ammo_rockets = AMMAX_ROCKETS;
}
if(e.ammo_cells > AMMAX_CELLS) {
e.ammo_cells = AMMAX_CELLS;
}
};
float(float w) RankForWeapon = {
switch(w) {
case IT_LIGHTNING: return 1;
case IT_ROCKET_LAUNCHER: return 2;
case IT_SUPER_NAILGUN: return 3;
case IT_GRENADE_LAUNCHER: return 4;
case IT_SUPER_SHOTGUN: return 5;
case IT_NAILGUN: return 6;
default: return 7;
}
};
/*
=============
Deathmatch_Weapon
Deathmatch weapon change rules for picking up a weapon
=============
*/
void(float old, float new) Deathmatch_Weapon = {
float or, nr;
// change self.weapon if desired
or = RankForWeapon(self.weapon);
nr = RankForWeapon(new);
if(nr < or) {
self.weapon = new;
}
};
/*
=============
weapon_touch
=============
*/
void() weapon_touch = {
float hadammo, best, new, old;
entity stemp;
float leave;
if(!(other.flags & FL_CLIENT)) {
return;
}
// if the player was using their best weapon, change up to the new one if
// better
stemp = self;
self = other;
best = W_BestWeapon();
self = stemp;
leave = (deathmatch == 2 || coop);
switch(self.classname) {
case "weapon_nailgun":
if(leave && other.items & IT_NAILGUN) {
return;
}
hadammo = other.ammo_nails;
new = IT_NAILGUN;
other.ammo_nails = other.ammo_nails + 30;
break;
case "weapon_supernailgun":
if(leave && other.items & IT_SUPER_NAILGUN) {
return;
}
hadammo = other.ammo_rockets;
new = IT_SUPER_NAILGUN;
other.ammo_nails = other.ammo_nails + 30;
break;
case "weapon_supershotgun":
if(leave && other.items & IT_SUPER_SHOTGUN) {
return;
}
hadammo = other.ammo_rockets;
new = IT_SUPER_SHOTGUN;
other.ammo_shells = other.ammo_shells + 5;
break;
case "weapon_rocketlauncher":
if(leave && other.items & IT_ROCKET_LAUNCHER) {
return;
}
hadammo = other.ammo_rockets;
new = IT_ROCKET_LAUNCHER;
other.ammo_rockets = other.ammo_rockets + 5;
break;
case "weapon_grenadelauncher":
if(leave && other.items & IT_GRENADE_LAUNCHER) {
return;
}
hadammo = other.ammo_rockets;
new = IT_GRENADE_LAUNCHER;
other.ammo_rockets = other.ammo_rockets + 5;
break;
case "weapon_lightning":
if(leave && other.items & IT_LIGHTNING) {
return;
}
hadammo = other.ammo_rockets;
new = IT_LIGHTNING;
other.ammo_cells = other.ammo_cells + 15;
break;
default:
objerror("weapon_touch: unknown classname");
}
sprint(other, "You got the ", self.netname, "\n");
// weapon touch sound
sound(other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
stuffcmd(other, "bf\n");
bound_ammo(other);
// change to the weapon
old = other.items;
other.items = other.items | new;
stemp = self;
self = other;
if(!deathmatch) {
self.weapon = new;
} else {
Deathmatch_Weapon(old, new);
}
W_SetCurrentAmmo();
self = stemp;
if(leave) {
return;
}
// remove it in single player, or setup for respawning in deathmatch
self.model = string_null;
self.solid = SOLID_NOT;
if(deathmatch == 1) {
self.nextthink = time + 30;
}
self.think = SUB_regen;
activator = other;
SUB_UseTargets(); // fire all targets / killtargets
};
/*QUAKED weapon_supershotgun(0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() weapon_supershotgun = {
precache_model("progs/g_shot.mdl");
setmodel(self, "progs/g_shot.mdl");
self.weapon = IT_SUPER_SHOTGUN;
self.netname = WEPNAME_SUPER_SHOTGUN;
self.touch = weapon_touch;
setsize(self, '-16 -16 0', '16 16 56');
StartItem();
};
/*QUAKED weapon_nailgun(0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() weapon_nailgun = {
precache_model("progs/g_nail.mdl");
setmodel(self, "progs/g_nail.mdl");
self.weapon = IT_NAILGUN;
self.netname = WEPNAME_NAILGUN;
self.touch = weapon_touch;
setsize(self, '-16 -16 0', '16 16 56');
StartItem();
};
/*QUAKED weapon_supernailgun(0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() weapon_supernailgun = {
precache_model("progs/g_nail2.mdl");
setmodel(self, "progs/g_nail2.mdl");
self.weapon = IT_SUPER_NAILGUN;
self.netname = WEPNAME_SUPER_NAILGUN;
self.touch = weapon_touch;
setsize(self, '-16 -16 0', '16 16 56');
StartItem();
};
/*QUAKED weapon_grenadelauncher(0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() weapon_grenadelauncher = {
precache_model("progs/g_rock.mdl");
setmodel(self, "progs/g_rock.mdl");
self.weapon = 3;
self.netname = WEPNAME_GRENADE_LAUNCHER;
self.touch = weapon_touch;
setsize(self, '-16 -16 0', '16 16 56');
StartItem();
};
/*QUAKED weapon_rocketlauncher(0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() weapon_rocketlauncher = {
precache_model("progs/g_rock2.mdl");
setmodel(self, "progs/g_rock2.mdl");
self.weapon = 3;
self.netname = WEPNAME_ROCKET_LAUNCHER;
self.touch = weapon_touch;
setsize(self, '-16 -16 0', '16 16 56');
StartItem();
};
/*QUAKED weapon_lightning(0 .5 .8) (-16 -16 0) (16 16 32)
*/
void() weapon_lightning = {
precache_model("progs/g_light.mdl");
setmodel(self, "progs/g_light.mdl");
self.weapon = 3;
self.netname = WEPNAME_LIGHTNING;
self.touch = weapon_touch;
setsize(self, '-16 -16 0', '16 16 56');
StartItem();
};
/*
===============================================================================
AMMO
===============================================================================
*/
void(.float ammo, float max) distribute_ammo = {
entity pl, stemp;
if(sf_dist_ammo) {
pl = find(world, classname, "player");
while(pl != world) {
pl.ammo += self.aflag;
bound_ammo(pl);
stemp = self;
self = pl;
W_SetCurrentAmmo();
self = stemp;
pl = find(pl, classname, "player");
}
} else {
if(other.ammo >= max) {
return;
}
other.ammo += self.aflag;
bound_ammo(other);
}
};
void() ammo_touch = {
entity stemp;
float best;
if(other.classname != "player" || other.health <= 0) {
return;
}
// if the player was using their best weapon, change up to the new one if
// better
stemp = self;
self = other;
best = W_BestWeapon();
self = stemp;
switch(self.weapon) {
case AMTYPE_SHELLS:
distribute_ammo(ammo_shells, AMMAX_SHELLS);
break;
case AMTYPE_NAILS:
distribute_ammo(ammo_nails, AMMAX_NAILS);
break;
case AMTYPE_ROCKETS:
distribute_ammo(ammo_rockets, AMMAX_ROCKETS);
break;
case AMTYPE_CELLS:
distribute_ammo(ammo_cells, AMMAX_CELLS);
break;
}
sprint(other, "You got the ", self.netname, "\n");
// ammo touch sound
sound(other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
stuffcmd(other, "bf\n");
// change to a better weapon if appropriate
if(other.weapon == best) {
stemp = self;
self = other;
self.weapon = W_BestWeapon();
W_SetCurrentAmmo();
self = stemp;
}
// if changed current ammo, update it
stemp = self;
self = other;
W_SetCurrentAmmo();
self = stemp;
// remove it in single player, or setup for respawning in deathmatch
self.model = string_null;
self.solid = SOLID_NOT;
if(deathmatch == 1) {
self.nextthink = time + 30;
}
self.think = SUB_regen;
activator = other;
SUB_UseTargets(); // fire all targets / killtargets
};
/*QUAKED item_shells(0 .5 .8) (0 0 0) (32 32 32) big
*/
void() item_shells = {
self.touch = ammo_touch;
if(self.spawnflags & AMMO_BIG) {
precache_model("maps/b_shell1.bsp");
setmodel(self, "maps/b_shell1.bsp");
self.aflag = 40;
} else {
precache_model("maps/b_shell0.bsp");
setmodel(self, "maps/b_shell0.bsp");
self.aflag = 20;
}
self.weapon = 1;
self.netname = "shells";
setsize(self, VEC_ORIGIN, '32 32 56');
StartItem();
};
/*QUAKED item_spikes(0 .5 .8) (0 0 0) (32 32 32) big
*/
void() item_spikes = {
self.touch = ammo_touch;
if(self.spawnflags & AMMO_BIG) {
precache_model("maps/b_nail1.bsp");
setmodel(self, "maps/b_nail1.bsp");
self.aflag = 50;
} else {
precache_model("maps/b_nail0.bsp");
setmodel(self, "maps/b_nail0.bsp");
self.aflag = 25;
}
self.weapon = 2;
self.netname = "nails";
setsize(self, VEC_ORIGIN, '32 32 56');
StartItem();
};
/*QUAKED item_rockets(0 .5 .8) (0 0 0) (32 32 32) big
*/
void() item_rockets = {
self.touch = ammo_touch;
if(self.spawnflags & AMMO_BIG) {
precache_model("maps/b_rock1.bsp");
setmodel(self, "maps/b_rock1.bsp");
self.aflag = 10;
} else {
precache_model("maps/b_rock0.bsp");
setmodel(self, "maps/b_rock0.bsp");
self.aflag = 5;
}
self.weapon = 3;
self.netname = "rockets";
setsize(self, VEC_ORIGIN, '32 32 56');
StartItem();
};
/*QUAKED item_cells(0 .5 .8) (0 0 0) (32 32 32) big
*/
void() item_cells = {
self.touch = ammo_touch;
if(self.spawnflags & AMMO_BIG) {
precache_model("maps/b_batt1.bsp");
setmodel(self, "maps/b_batt1.bsp");
self.aflag = 12;
} else {
precache_model("maps/b_batt0.bsp");
setmodel(self, "maps/b_batt0.bsp");
self.aflag = 6;
}
self.weapon = 4;
self.netname = "cells";
setsize(self, VEC_ORIGIN, '32 32 56');
StartItem();
};
/*
===============================================================================
KEYS
===============================================================================
*/
void() key_touch = {
entity stemp;
float best;
if(other.classname != "player" ||
other.health <= 0 ||
other.items & self.items) {
return;
}
sprint(other, "You got the ", self.netname, "\n");
sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
stuffcmd(other, "bf\n");
other.items = other.items | self.items;
if(!coop) {
self.solid = SOLID_NOT;
self.model = string_null;
}
activator = other;
SUB_UseTargets(); // fire all targets / killtargets
};
void() key_setsounds = {
switch(world.worldtype) {
case WORLD_MEDIEVAL:
precache_sound("misc/medkey.wav");
self.noise = "misc/medkey.wav";
break;
case WORLD_METAL:
precache_sound("misc/runekey.wav");
self.noise = "misc/runekey.wav";
break;
case WORLD_BASE:
precache_sound2("misc/basekey.wav");
self.noise = "misc/basekey.wav";
break;
}
};
/*QUAKED item_key1(0 .5 .8) (-16 -16 -24) (16 16 32)
SILVER key
In order for keys to work
you MUST set your maps
worldtype to one of the
following:
0: medieval
1: metal
2: base
*/
void() item_key1 = {
self.netname = Key1Name();
switch(world.worldtype) {
case WORLD_MEDIEVAL:
precache_model("progs/w_s_key.mdl");
setmodel(self, "progs/w_s_key.mdl");
break;
case WORLD_METAL:
precache_model("progs/m_s_key.mdl");
setmodel(self, "progs/m_s_key.mdl");
break;
case WORLD_BASE:
precache_model2("progs/b_s_key.mdl");
setmodel(self, "progs/b_s_key.mdl");
break;
}
key_setsounds();
self.touch = key_touch;
self.items = IT_KEY1;
setsize(self, '-16 -16 -24', '16 16 32');
StartItem();
};
/*QUAKED item_key2(0 .5 .8) (-16 -16 -24) (16 16 32)
GOLD key
In order for keys to work
you MUST set your maps
worldtype to one of the
following:
0: medieval
1: metal
2: base
*/
void() item_key2 = {
self.netname = Key2Name();
switch(world.worldtype) {
case WORLD_MEDIEVAL:
precache_model("progs/w_g_key.mdl");
setmodel(self, "progs/w_g_key.mdl");
break;
case WORLD_METAL:
precache_model("progs/m_g_key.mdl");
setmodel(self, "progs/m_g_key.mdl");
break;
case WORLD_BASE:
precache_model2("progs/b_g_key.mdl");
setmodel(self, "progs/b_g_key.mdl");
break;
}
key_setsounds();
self.touch = key_touch;
self.items = IT_KEY2;
setsize(self, '-16 -16 -24', '16 16 32');
StartItem();
};
/*
===============================================================================
END OF LEVEL RUNES
===============================================================================
*/
void() sigil_touch = {
entity stemp;
float best;
if(other.classname != "player" || other.health <= 0) {
return;
}
centerprint(other, "You got the rune!");
sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
stuffcmd(other, "bf\n");
self.solid = SOLID_NOT;
self.model = string_null;
serverflags = serverflags | (self.spawnflags & 15);
self.classname = string_null; // so rune doors won't find it
activator = other;
SUB_UseTargets(); // fire all targets / killtargets
};
/*QUAKED item_sigil(0 .5 .8) (-16 -16 -24) (16 16 32) E1 E2 E3 E4
End of level sigil, pick up to end episode and return to jrstart.
*/
void() item_sigil = {
if(!self.spawnflags) {
objerror("no spawnflags");
}
precache_sound("misc/runekey.wav");
self.noise = "misc/runekey.wav";
if(self.spawnflags & SIGIL_1) {
precache_model("progs/end1.mdl");
setmodel(self, "progs/end1.mdl");
}
if(self.spawnflags & SIGIL_2) {
precache_model2("progs/end2.mdl");
setmodel(self, "progs/end2.mdl");
}
if(self.spawnflags & SIGIL_3) {
precache_model2("progs/end3.mdl");
setmodel(self, "progs/end3.mdl");
}
if(self.spawnflags & SIGIL_4) {
precache_model2("progs/end4.mdl");
setmodel(self, "progs/end4.mdl");
}
self.touch = sigil_touch;
setsize(self, '-16 -16 -24', '16 16 32');
StartItem();
};
/*
===============================================================================
POWERUPS
===============================================================================
*/
void() powerup_touch = {
entity stemp;
float best;
if(other.classname != "player" || other.health <= 0) {
return;
}
sprint(other, "You got the ", self.netname, "\n");
if(deathmatch) {
self.mdl = self.model;
if(self.classname == "item_artifact_invulnerability" ||
self.classname == "item_artifact_invisibility") {
self.nextthink = time + 60 * 5;
} else {
self.nextthink = time + 60;
}
self.think = SUB_regen;
}
sound(other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
stuffcmd(other, "bf\n");
self.solid = SOLID_NOT;
other.items = other.items | self.items;
self.model = string_null;
// do the apropriate action
if(self.classname == "item_artifact_envirosuit") {
other.rad_time = 1;
other.radsuit_finished = time + 30;
}
if(self.classname == "item_artifact_invulnerability") {
other.invincible_time = 1;
other.invincible_finished = time + 30;
}
if(self.classname == "item_artifact_invisibility") {
other.invisible_time = 1;
other.invisible_finished = time + 30;
}
if(self.classname == "item_artifact_super_damage") {
other.super_time = 1;
other.super_damage_finished = time + 30;
}
activator = other;
SUB_UseTargets(); // fire all targets / killtargets
};
/*QUAKED item_artifact_invulnerability(0 .5 .8) (-16 -16 -24) (16 16 32)
Player is invulnerable for 30 seconds
*/
void() item_artifact_invulnerability = {
self.touch = powerup_touch;
precache_model("progs/invulner.mdl");
precache_sound("items/protect.wav");
precache_sound("items/protect2.wav");
precache_sound("items/protect3.wav");
self.noise = "items/protect.wav";
setmodel(self, "progs/invulner.mdl");
self.netname = "Pentagram of Protection";
self.items = IT_INVULNERABILITY;
setsize(self, '-16 -16 -24', '16 16 32');
StartItem();
};
/*QUAKED item_artifact_envirosuit(0 .5 .8) (-16 -16 -24) (16 16 32)
Player takes no damage from water or slime for 30 seconds
*/
void() item_artifact_envirosuit = {
self.touch = powerup_touch;
precache_model("progs/suit.mdl");
precache_sound("items/suit.wav");
precache_sound("items/suit2.wav");
self.noise = "items/suit.wav";
setmodel(self, "progs/suit.mdl");
self.netname = "Biosuit";
self.items = IT_SUIT;
setsize(self, '-16 -16 -24', '16 16 32');
StartItem();
};
/*QUAKED item_artifact_invisibility(0 .5 .8) (-16 -16 -24) (16 16 32)
Player is invisible for 30 seconds
*/
void() item_artifact_invisibility = {
self.touch = powerup_touch;
precache_model("progs/invisibl.mdl");
precache_sound("items/inv1.wav");
precache_sound("items/inv2.wav");
precache_sound("items/inv3.wav");
self.noise = "items/inv1.wav";
setmodel(self, "progs/invisibl.mdl");
self.netname = "Ring of Shadows";
self.items = IT_INVISIBILITY;
setsize(self, '-16 -16 -24', '16 16 32');
StartItem();
};
/*QUAKED item_artifact_super_damage(0 .5 .8) (-16 -16 -24) (16 16 32)
The next attack from the player will do 4x damage
*/
void() item_artifact_super_damage = {
self.touch = powerup_touch;
precache_model("progs/quaddama.mdl");
precache_sound("items/damage.wav");
precache_sound("items/damage2.wav");
precache_sound("items/damage3.wav");
self.noise = "items/damage.wav";
setmodel(self, "progs/quaddama.mdl");
self.netname = "Quad Damage";
self.items = IT_QUAD;
setsize(self, '-16 -16 -24', '16 16 32');
StartItem();
};
/*
===============================================================================
PLAYER BACKPACKS
===============================================================================
*/
void() BackpackTouch = {
float best, old, new;
entity stemp;
float acount;
if(other.classname != "player" || other.health <= 0) {
return;
}
acount = 0;
sprint(other, "You get ");
if(self.weapon && (other.items & self.weapon) == 0) {
acount = 1;
sprint(other, "the ", self.netname);
}
// if the player was using their best weapon, change up to the new one if
// better
stemp = self;
self = other;
best = W_BestWeapon();
self = stemp;
// change weapons
other.ammo_shells = other.ammo_shells + self.ammo_shells;
other.ammo_nails = other.ammo_nails + self.ammo_nails;
other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
other.ammo_cells = other.ammo_cells + self.ammo_cells;
new = self.items;
if(!new) {
new = other.weapon;
}
old = other.items;
other.items = other.items | new;
bound_ammo(other);
if(self.ammo_shells) {
if(acount) {
sprint(other, ", ");
}
acount = 1;
sprint(other, ftos(self.ammo_shells), " shells");
}
if(self.ammo_nails) {
if(acount) {
sprint(other, ", ");
}
acount = 1;
sprint(other, ftos(self.ammo_nails), " nails");
}
if(self.ammo_rockets) {
if(acount) {
sprint(other, ", ");
}
acount = 1;
sprint(other, ftos(self.ammo_rockets), " rockets");
}
if(self.ammo_cells) {
if(acount) {
sprint(other, ", ");
}
acount = 1;
sprint(other, ftos(self.ammo_cells), " cells");
}
if(self.items & IT_KEY1) {
if(acount) {
sprint(other, ", ");
}
acount = 1;
sprint(other, Key1Name());
}
if(self.items & IT_KEY2) {
if(acount) {
sprint(other, ", ");
}
acount = 1;
sprint(other, Key2Name());
}
sprint(other, "\n");
// backpack touch sound
sound(other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
stuffcmd(other, "bf\n");
// remove the backpack, change self to the player
remove(self);
self = other;
// change to the weapon
if(!deathmatch) {
self.weapon = new;
} else {
Deathmatch_Weapon(old, new);
}
W_SetCurrentAmmo();
};
/*
===============
DropBackpack
===============
*/
entity() DropBackpack = {
entity item;
item = spawn();
item.origin = self.origin - '0 0 24';
item.items = self.weapon | (self.items & (IT_KEY1 | IT_KEY2));
item.weapon = self.weapon;
switch(item.weapon) {
case IT_AXE:
item.netname = WEPNAME_AXE;
break;
case IT_SHOTGUN:
item.netname = WEPNAME_SHOTGUN;
break;
case IT_SUPER_SHOTGUN:
item.netname = WEPNAME_SUPER_SHOTGUN;
break;
case IT_NAILGUN:
item.netname = WEPNAME_NAILGUN;
break;
case IT_SUPER_NAILGUN:
item.netname = WEPNAME_SUPER_NAILGUN;
break;
case IT_GRENADE_LAUNCHER:
item.netname = WEPNAME_GRENADE_LAUNCHER;
break;
case IT_ROCKET_LAUNCHER:
item.netname = WEPNAME_ROCKET_LAUNCHER;
break;
case IT_LIGHTNING:
item.netname = WEPNAME_LIGHTNING;
break;
default:
item.netname = string_null;
break;
}
item.ammo_shells = self.ammo_shells;
item.ammo_nails = self.ammo_nails;
item.ammo_rockets = self.ammo_rockets;
item.ammo_cells = self.ammo_cells;
item.velocity_z = 300;
item.velocity_x = -100 + (random() * 200);
item.velocity_y = -100 + (random() * 200);
item.flags = FL_ITEM;
item.solid = SOLID_TRIGGER;
item.movetype = MOVETYPE_TOSS;
setmodel(item, "progs/backpack.mdl");
setsize(item, '-16 -16 0', '16 16 56');
item.touch = BackpackTouch;
item.nextthink = time + 120; // remove after 2 minutes
item.think = SUB_Remove;
return item;
};