Too lazy to comment
This commit is contained in:
357
mod_xj18/my_progs/client_debuff.qc
Normal file
357
mod_xj18/my_progs/client_debuff.qc
Normal file
@@ -0,0 +1,357 @@
|
||||
/*======================================================================
|
||||
CheckDeBuff - Check for negative buffs affecting the player
|
||||
======================================================================*/
|
||||
|
||||
.float cshift_upd; // Screen updates (v_cshift) are active
|
||||
.float cshift_time; // Timer (0.1s tick) for screen updates
|
||||
.vector cshift_col; // RGB / XYZ values for screen colour
|
||||
.float cshift_den; // Screen colour density
|
||||
.float cshift_step; // Quantity to reduce density by per tick
|
||||
|
||||
.float debuff_sound; // Heartbeat sound when tick happens
|
||||
.float debuff_qty; // Quantity to do something with (temp)
|
||||
|
||||
.float bleeding; // Bleeding debuff status
|
||||
.float bleeding_time; // Timer (1s tick) for screen/sound update
|
||||
.float bleeding_qty; // Total amount of health stored (HoT)
|
||||
|
||||
.float burning; // Burning debuff status
|
||||
.float burning_time; // Timer (1s tick) for screen/sound update
|
||||
.float burning_qty; // Total amount of damage stored (DoT)
|
||||
|
||||
.float poisoned; // Poison debuff status
|
||||
.float poisoned_time; // Timer (1s tick) for screen/sound update
|
||||
.float poisoned_qty; // Total amount of damage stored (DoT)
|
||||
|
||||
// IT_INVISIBILITY + IT_INVULNERABILITY + IT_SUIT + IT_QUAD
|
||||
// 524288 + 1048576 + 2097152 + 4194304
|
||||
float ALL_ITARTIFACTS = 7864320;
|
||||
|
||||
// Wraith Health drain
|
||||
vector DEBUFF_BLEED_COL = '200 0 0'; // Strong red
|
||||
float DEBUFF_BLEED_DEN = 120;
|
||||
float DEBUFF_BLEED_STEP = 10;
|
||||
float DEBUFF_BLEED_HEAL = 5;
|
||||
float DEBUFF_BLEED_MIN = 5;
|
||||
|
||||
// Pyro flame burn
|
||||
vector DEBUFF_BURN_COL = '200 100 0'; // Orange
|
||||
float DEBUFF_BURN_DEN = 120;
|
||||
float DEBUFF_BURN_STEP = 10;
|
||||
float DEBUFF_BURN_DMG = 1;
|
||||
float DEBUFF_BURN_MAX = 10;
|
||||
|
||||
// Mummy poisoned gibs
|
||||
vector DEBUFF_POISON_COL = '0 200 0'; // Strong Green
|
||||
float DEBUFF_POISON_DEN = 84;
|
||||
float DEBUFF_POISON_STEP = 7;
|
||||
float DEBUFF_POISON_DMG = 1;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Various debuff reset functions, used all over the place
|
||||
//----------------------------------------------------------------------
|
||||
void(entity targ) ResetDebuffScreen =
|
||||
{
|
||||
targ.cshift_upd = FALSE;
|
||||
targ.cshift_time = LARGE_TIMER;
|
||||
stuffcmd(targ, "v_cshift 0 0 0 0\n");
|
||||
targ.cshift_col = '0 0 0';
|
||||
targ.cshift_den = 0;
|
||||
};
|
||||
|
||||
void(entity targ) ResetDebuffBurning =
|
||||
{ targ.burning = targ.burning_qty = 0; };
|
||||
|
||||
void(entity targ) ResetDebuffPoisoned =
|
||||
{ targ.poisoned = targ.poisoned_qty = 0; };
|
||||
|
||||
void(entity targ) ResetDebuffBleeding =
|
||||
{ targ.bleeding = targ.bleeding_qty = 0; };
|
||||
|
||||
void(entity targ) ResetDebuffSystem =
|
||||
{
|
||||
ResetDebuffScreen(targ);
|
||||
ResetDebuffBurning(targ);
|
||||
ResetDebuffPoisoned(targ);
|
||||
ResetDebuffBleeding(targ);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Core debuff function, run every frame from client.qc
|
||||
//----------------------------------------------------------------------
|
||||
void() ClientDeBuff =
|
||||
{
|
||||
// If player is dead or intermission running, turn everything off
|
||||
if (intermission_running > 0 || self.health < 1) {
|
||||
ResetDebuffSystem(self);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for burning debuff (DoT)
|
||||
if (self.burning) {
|
||||
// Is it time for a debuff update
|
||||
if (self.burning_time < time) {
|
||||
if (self.burning_qty > 0) {
|
||||
// Reset burning tick timer
|
||||
self.burning_time = time + 1;
|
||||
|
||||
// Give priority to bleeding(heal) and poisoned
|
||||
if (!self.bleeding && !self.poisoned) {
|
||||
if (self.debuff_sound < time) self.debuff_sound = time + 1;
|
||||
self.cshift_upd = TRUE; // Update screen colour
|
||||
self.cshift_time = -1; // Update striaght away
|
||||
self.cshift_col = DEBUFF_BURN_COL;
|
||||
self.cshift_den = DEBUFF_BURN_DEN;
|
||||
self.cshift_step = DEBUFF_BURN_STEP;
|
||||
}
|
||||
|
||||
// Setup default burning damage
|
||||
self.debuff_qty = DEBUFF_BURN_DMG;
|
||||
// Check burning does not exceed stored damage
|
||||
if (self.burning_qty < self.debuff_qty) self.debuff_qty = self.burning_qty;
|
||||
// Subtract burning damage from counters
|
||||
self.burning_qty = self.burning_qty - self.debuff_qty;
|
||||
|
||||
// Use global damage function (has death checks)
|
||||
T_Damage (self, world, world, self.debuff_qty, NOARMOR);
|
||||
}
|
||||
}
|
||||
// Check if player is in water up to waist?
|
||||
// 0 = not in, 1 = feet, 2 = waist, 3 = eyes
|
||||
if (self.waterlevel >= 2 || self.burning_qty < 1) {
|
||||
ResetDebuffBurning(self);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for poisoned debuff (DoT)
|
||||
if (self.poisoned) {
|
||||
// Is it time for a debuff update
|
||||
if (self.poisoned_time < time) {
|
||||
if (self.poisoned_qty > 0) {
|
||||
// Reset poisoned tick timer
|
||||
self.poisoned_time = time + 1;
|
||||
|
||||
// Give priority to bleeding(heal)
|
||||
if (!self.bleeding) {
|
||||
if (self.debuff_sound < time) self.debuff_sound = time + 1;
|
||||
self.cshift_upd = TRUE; // Update screen colour
|
||||
self.cshift_time = -1; // Update striaght away
|
||||
self.cshift_col = DEBUFF_POISON_COL;
|
||||
self.cshift_den = DEBUFF_POISON_DEN;
|
||||
self.cshift_step = DEBUFF_POISON_STEP;
|
||||
}
|
||||
|
||||
// Setup default poison damage
|
||||
self.debuff_qty = DEBUFF_POISON_DMG;
|
||||
// Check poison does not exceed damage left
|
||||
if (self.poisoned_qty < self.debuff_qty) self.debuff_qty = self.poisoned_qty;
|
||||
// Subtract poison damage from counters
|
||||
self.poisoned_qty = self.poisoned_qty - self.debuff_qty;
|
||||
|
||||
// Use global damage function (has death checks)
|
||||
T_Damage (self, world, world, self.debuff_qty, NOARMOR);
|
||||
}
|
||||
}
|
||||
// Check if poison has finished?
|
||||
if (self.poisoned_qty < 1) ResetDebuffPoisoned(self);
|
||||
}
|
||||
|
||||
// Check for bleeding debuff (HoT)
|
||||
if (self.bleeding) {
|
||||
// Is it time for a debuff update
|
||||
if (self.bleeding_time < time) {
|
||||
if (self.bleeding_qty > 0) {
|
||||
// Reset bleeding(healing) tick timer
|
||||
self.bleeding_time = time + 1;
|
||||
if (self.debuff_sound < time) self.debuff_sound = time + 1;
|
||||
self.cshift_upd = TRUE; // Update screen colour
|
||||
self.cshift_time = -1; // Update striaght away
|
||||
self.cshift_col = DEBUFF_BLEED_COL;
|
||||
self.cshift_den = DEBUFF_BLEED_DEN;
|
||||
self.cshift_step = DEBUFF_BLEED_STEP;
|
||||
|
||||
// Setup default healing
|
||||
self.debuff_qty = DEBUFF_BLEED_HEAL;
|
||||
// Check healing does not exceed current reserve
|
||||
if (self.bleeding_qty < self.debuff_qty) self.debuff_qty = self.bleeding_qty;
|
||||
// Subtract bleeding heals from counters
|
||||
self.bleeding_qty = self.bleeding_qty - self.debuff_qty;
|
||||
// Check healing does not go over max player limit
|
||||
if (self.health + self.debuff_qty > self.max_health)
|
||||
self.debuff_qty = self.max_health - self.health;
|
||||
|
||||
// Directly add health back to player
|
||||
self.health = self.health + self.debuff_qty;
|
||||
}
|
||||
}
|
||||
// Check if player is over max health or run out of healing
|
||||
if (self.health >= self.max_health || self.bleeding_qty < 1) {
|
||||
ResetDebuffBleeding(self);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any debuff screen updates?
|
||||
if (self.cshift_upd) {
|
||||
// Play different debuff sounds (pressure is on!)
|
||||
if (self.debuff_sound > time) {
|
||||
self.debuff_sound = -1; // Reset
|
||||
|
||||
// Sound exception for god/pentagram mode
|
||||
if (self.flags & FL_GODMODE || self.invincible_finished >= time) {
|
||||
if (self.invincible_sound < time) {
|
||||
sound (self, CHAN_VOICE, SOUND_ARTPENT3, 1, ATTN_NORM);
|
||||
self.invincible_sound = time + 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Play heartbeat only for bleeding/healing
|
||||
if (self.bleeding)
|
||||
sound (self, CHAN_VOICE, SOUND_HEARTBEAT, 1, ATTN_IDLE);
|
||||
// Re-use player pain sounds
|
||||
else if (self.poisoned) {
|
||||
if (random() < 0.5) sound (self, CHAN_VOICE, "player/pain2.wav", 1, ATTN_IDLE);
|
||||
else sound (self, CHAN_VOICE, "player/pain3.wav", 1, ATTN_IDLE);
|
||||
}
|
||||
// Play on the same channel as player pain
|
||||
else if (self.burning) {
|
||||
if (random() < 0.5) sound (self, CHAN_VOICE, "player/pain1.wav", 1, ATTN_IDLE);
|
||||
else sound (self, CHAN_VOICE, "player/pain4.wav", 1, ATTN_IDLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for screen update? 0.1s tick interval
|
||||
if (self.cshift_time < time) {
|
||||
// Generate some particles based on debuff
|
||||
// Priority is bleeding > poisoned > burning
|
||||
if (self.bleeding) particle_debuff(self.origin, 16, rint(1+random()*4), PARTICLE_BURST_RED);
|
||||
else if (self.poisoned) particle_debuff(self.origin, 16, rint(1+random()*4), PARTICLE_BURST_GREEN);
|
||||
else if (self.burning) particle_debuff(self.origin, 16, rint(1+random()*4), PARTICLE_BURST_YELLOW);
|
||||
|
||||
// Count down density and check for reset condition
|
||||
self.cshift_den = self.cshift_den - self.cshift_step;
|
||||
if (self.cshift_den < 1) ResetDebuffScreen(self);
|
||||
else {
|
||||
// Update screen using stuffcmds!
|
||||
self.cshift_time = time + 0.1;
|
||||
|
||||
// Don't update the screen if an artifact is active
|
||||
// The engine will be updating at the same time
|
||||
if (self.items & ALL_ITARTIFACTS == 0) {
|
||||
stuffcmd(self, "v_cshift ");
|
||||
stuffcmd(self, ftos(rint(self.cshift_col_x)));
|
||||
stuffcmd(self, " ");
|
||||
stuffcmd(self, ftos(rint(self.cshift_col_y)));
|
||||
stuffcmd(self, " ");
|
||||
stuffcmd(self, ftos(rint(self.cshift_col_z)));
|
||||
stuffcmd(self, " ");
|
||||
stuffcmd(self, ftos(rint(self.cshift_den)));
|
||||
stuffcmd(self, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Reset cshift if nothing is active (engine does not reset)
|
||||
// This is to catch new games or quickload resets
|
||||
else if (self.cshift_time < time) ResetDebuffScreen(self);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void(entity targ) BleedDeBuff =
|
||||
{
|
||||
local float debuffqty;
|
||||
|
||||
// Check for minimum amount of health for debuff
|
||||
// Immune to debuff if using Pent of Protection or BioSuit
|
||||
if (targ.health < DEBUFF_BLEED_MIN) return;
|
||||
if (targ.flags & FL_CLIENT == FALSE) return;
|
||||
if (targ.items & (IT_INVULNERABILITY | IT_SUIT)) {
|
||||
T_Damage (targ, self, self, DAMGE_WRAITHBOLT, DAMARMOR);
|
||||
return;
|
||||
}
|
||||
|
||||
// if debuff not active, starting bleeding!
|
||||
if (!targ.bleeding) {
|
||||
targ.bleeding = TRUE;
|
||||
targ.bleeding_time = -1;
|
||||
}
|
||||
|
||||
// Take health from player and store it
|
||||
debuffqty = rint(targ.health * 0.5);
|
||||
T_Damage (targ, self, self, debuffqty, NOARMOR);
|
||||
targ.bleeding_qty = targ.bleeding_qty + debuffqty;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void(entity targ) BurnDeBuff =
|
||||
{
|
||||
local float debuffqty;
|
||||
|
||||
// Do not stack burning time beyond a certain limit
|
||||
// Cannot be burning if knee deep in water
|
||||
// Immune to debuff if using Pent of Protection or BioSuit
|
||||
if (targ.burning_qty > DEBUFF_BURN_MAX) return;
|
||||
if (targ.flags & FL_CLIENT == FALSE) return;
|
||||
if (targ.waterlevel >= 3) return;
|
||||
if (targ.items & (IT_INVULNERABILITY | IT_SUIT)) return;
|
||||
|
||||
// if debuff not active, starting burning!
|
||||
if (!targ.burning) {
|
||||
targ.burning = TRUE;
|
||||
targ.burning_time = -1;
|
||||
}
|
||||
|
||||
// work out time remaining on debuff
|
||||
debuffqty = rint(5*skill + 3 + 2*random());
|
||||
targ.burning_qty = targ.burning_qty + debuffqty;
|
||||
if (targ.burning_qty > DEBUFF_BURN_MAX) targ.burning_qty = DEBUFF_BURN_MAX;
|
||||
|
||||
targ.cshift_upd = TRUE; // Update screen colour
|
||||
targ.cshift_time = -1; // Update striaght away
|
||||
targ.cshift_col = DEBUFF_BURN_COL;
|
||||
targ.cshift_den = DEBUFF_BURN_DEN;
|
||||
targ.cshift_step = DEBUFF_BURN_STEP;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void(entity targ) PoisonDeBuff =
|
||||
{
|
||||
local float debuffqty;
|
||||
|
||||
// Immune to debuff if using Pent of Protection or BioSuit
|
||||
if (targ.flags & FL_CLIENT == FALSE) return;
|
||||
if (targ.items & (IT_INVULNERABILITY | IT_SUIT)) return;
|
||||
if (targ.poisoned) return; // Only poison once
|
||||
|
||||
// if debuff not active, start poison!
|
||||
targ.poisoned = TRUE;
|
||||
targ.poisoned_time = -1;
|
||||
// work out time remaining on debuff
|
||||
debuffqty = rint(skill + 3 + 2*random());
|
||||
targ.poisoned_qty = targ.poisoned_qty + debuffqty;
|
||||
|
||||
targ.cshift_upd = TRUE; // Update screen colour
|
||||
targ.cshift_time = -1; // Update striaght away
|
||||
targ.cshift_col = DEBUFF_POISON_COL;
|
||||
targ.cshift_den = DEBUFF_POISON_DEN;
|
||||
targ.cshift_step = DEBUFF_POISON_STEP;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Used by Pyro and Wraith; consistent damage from both monsters
|
||||
//----------------------------------------------------------------------
|
||||
void(entity targ, float playdmg, float mondmg) ApplyFireDmg =
|
||||
{
|
||||
local float reduction, firedamage;
|
||||
|
||||
// Bio suit reduction - easy=80%, normal=70%, hard=60%, nm=50%
|
||||
reduction = 0.2 + skill * 0.1;
|
||||
|
||||
// Damage is different for monsters/players
|
||||
if (targ.flags & FL_MONSTER) firedamage = mondmg;
|
||||
else if (targ.items & IT_SUIT) firedamage = rint(playdmg * reduction);
|
||||
else firedamage = playdmg;
|
||||
|
||||
// Final damage (no armour save)
|
||||
T_Damage (targ, self, self.owner, firedamage, NOARMOR);
|
||||
BurnDeBuff(targ);
|
||||
};
|
||||
Reference in New Issue
Block a user