407 lines
13 KiB
Plaintext
407 lines
13 KiB
Plaintext
/*======================================================================
|
|
Client Map Variables
|
|
--------------------
|
|
|
|
Allows for binary (0/1) map variables to be stored with the map save
|
|
system (parm1-16) by the engine. The top 6 parm variables are never used
|
|
and can easily be turned into variables for the map to use.
|
|
|
|
======================================================================*/
|
|
float MAPV_BITS = 22; // Bits used in each parm block
|
|
float MAPV_BLCK = 6; // Blocks used (total parm's)
|
|
float MAPV_TOTAL = 132; // Maximum amount of variables
|
|
|
|
float MAPV_QUERY = 1; // Point entity - Query value
|
|
float MAPV_UPDATE = 2; // Point entity - Update value
|
|
float MAPV_TOGGLE = 4; // Point entity - Toggle value
|
|
float MAPV_MONSTERS = 32; // Monsters can use bmodel trigger
|
|
|
|
float bitflags[24]; // Bitflag values
|
|
float mapvar[6]; // Map variables stored in savefile
|
|
|
|
//======================================================================
|
|
/*QUAKED trigger_mapvar_query (.5 .7 1) (-8 -8 -16) (8 8 16) x
|
|
Trigger target(s) based on mapvar
|
|
-------- KEYS --------
|
|
targetname : trigger entity (works with entity state system)
|
|
count : Map Variable to check (range checks)
|
|
target : Map variable == 0 fire these target(s)
|
|
target2 : Map variable == 1 fire these target(s)
|
|
noise : aframe switchable object
|
|
wait : -1 = trigger once
|
|
-------- SPAWNFLAGS --------
|
|
-------- NOTES --------
|
|
Trigger target(s) based on mapvar
|
|
//-----------------------------------------------------------------------------
|
|
/*QUAKED trigger_mapvar_update (.5 .7 1) (-8 -8 -16) (8 8 16) x
|
|
Update the value of mapvar
|
|
-------- KEYS --------
|
|
targetname : trigger entity (works with entity state system)
|
|
count : Map Variable to check (range checks)
|
|
cnt : Value (0/1)
|
|
target : Map variable == 0 fire these target(s)
|
|
target2 : Map variable == 1 fire these target(s)
|
|
noise : aframe switchable object
|
|
wait : -1 = trigger once
|
|
-------- SPAWNFLAGS --------
|
|
-------- NOTES --------
|
|
Update the value of mapvar
|
|
//-----------------------------------------------------------------------------
|
|
/*QUAKED trigger_mapvar_toggle (.5 .7 1) (-8 -8 -16) (8 8 16) x
|
|
Toggle the value of mapvar
|
|
-------- KEYS --------
|
|
targetname : trigger entity (works with entity state system)
|
|
count : Map Variable to check (range checks)
|
|
target : Map variable == 0 fire these target(s)
|
|
target2 : Map variable == 1 fire these target(s)
|
|
noise : aframe switchable object
|
|
wait : -1 = trigger once
|
|
-------- SPAWNFLAGS --------
|
|
-------- NOTES --------
|
|
Toggle the value of mapvar
|
|
======================================================================*/
|
|
|
|
// Setup the bitflag array (used in world.qc)
|
|
void() mapvar_setuparray =
|
|
{
|
|
local float bitindex, bitpow;
|
|
|
|
// Setup loop and first bit
|
|
bitindex = 0; bitpow = 1;
|
|
while (bitindex < 24) {
|
|
bitflags[bitindex] = bitpow;
|
|
bitpow = bitpow * 2;
|
|
bitindex = bitindex + 1;
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
// Reset all map variable banks to zero (used in client.qc)
|
|
void() mapvar_reset =
|
|
{
|
|
local float mapv_bank;
|
|
|
|
mapv_bank = 0;
|
|
while (mapv_bank < MAPV_BLCK) {
|
|
mapvar[mapv_bank] = 0;
|
|
mapv_bank = mapv_bank + 1;
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
// Read map variable from block/bits parms and return value
|
|
float(float mapv_indx) query_mapvar =
|
|
{
|
|
local float mapv_bank, mapv_cell, mapv_bit;
|
|
|
|
// Work out parm and bitflag index
|
|
mapv_bank = floor(mapv_indx/MAPV_BITS);
|
|
mapv_cell = mapv_indx - (mapv_bank*MAPV_BITS);
|
|
// Error check return value
|
|
if (mapv_bank < 0 || mapv_bank >= MAPV_BLCK) mapv_bank = 0;
|
|
if (mapv_cell < 0 || mapv_cell >= MAPV_BITS) mapv_cell = 0;
|
|
// Find bitflag mask value
|
|
mapv_bit = mapvar[mapv_bank] & bitflags[mapv_cell];
|
|
|
|
/* Debug info (not used anymore)
|
|
dprint("Number ("); dprint(ftos(mapv_indx));
|
|
dprint(") B/C ("); dprint(ftos(mapv_bank));
|
|
dprint(" "); dprint(ftos(mapv_cell));
|
|
dprint(") = ("); dprint(ftos(mapv_bit));
|
|
dprint(")\n"); */
|
|
|
|
if (mapv_bit > 0) return TRUE;
|
|
else return FALSE;
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
// Update map variable from block/bits parms
|
|
void(float mapv_indx, float mapv_val) update_mapvar =
|
|
{
|
|
local float mapv_bank, mapv_cell;
|
|
|
|
// Work out parm and bitflag index
|
|
mapv_bank = floor(mapv_indx/MAPV_BITS);
|
|
mapv_cell = mapv_indx - (mapv_bank*MAPV_BITS);
|
|
// Error check return value
|
|
if (mapv_bank < 0 || mapv_bank >= MAPV_BLCK) mapv_bank = 0;
|
|
if (mapv_cell < 0 || mapv_cell >= MAPV_BITS) mapv_cell = 0;
|
|
|
|
// Remove any existing bitflag value
|
|
mapvar[mapv_bank] = mapvar[mapv_bank] - (mapvar[mapv_bank] & bitflags[mapv_cell]);
|
|
|
|
// Is the bit value TRUE?
|
|
if (mapv_val == TRUE) {
|
|
mapvar[mapv_bank] = mapvar[mapv_bank] | bitflags[mapv_cell];
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
// Set a range of map variables (used in triggers.qc)
|
|
void(vector mapv_range) mapvar_range =
|
|
{
|
|
local vector mapv_dest;
|
|
local float mapv_swap, mapv_loop;
|
|
|
|
// Remove any negative or fractions
|
|
mapv_dest_x = fabs(rint(mapv_range_x));
|
|
mapv_dest_y = fabs(rint(mapv_range_y));
|
|
mapv_dest_z = fabs(rint(mapv_range_z));
|
|
|
|
// Check for upper variable range
|
|
if (mapv_dest_x >= (MAPV_BLCK*MAPV_BITS))
|
|
mapv_dest_x = (MAPV_BLCK*MAPV_BITS) - 1;
|
|
if (mapv_dest_y >= (MAPV_BLCK*MAPV_BITS))
|
|
mapv_dest_y = (MAPV_BLCK*MAPV_BITS) - 1;
|
|
if (mapv_dest_z > 1) mapv_dest_z = 1;
|
|
|
|
// Check for reverse order on range
|
|
if (mapv_dest_x > mapv_dest_y) {
|
|
mapv_swap = mapv_dest_x;
|
|
mapv_dest_x = mapv_dest_y;
|
|
mapv_dest_y = mapv_swap;
|
|
}
|
|
|
|
// Count through range
|
|
mapv_loop = mapv_dest_x;
|
|
while (mapv_loop <= mapv_dest_y) {
|
|
// Change map variable
|
|
update_mapvar(mapv_loop, mapv_dest_z);
|
|
mapv_loop = mapv_loop + 1;
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
// Display the value of all map variable parm blocks
|
|
void() display_mapvar =
|
|
{
|
|
local float loopbank, loopcell, loopspace, loopval;
|
|
|
|
// Default return conditions (must be player and developer)
|
|
if ( !(self.flags & FL_CLIENT) ) return;
|
|
if (developer == 0) {
|
|
sprint(self,"\b[IMPULSE]\b Only works in developer mode!\n");
|
|
return;
|
|
}
|
|
// Has the map variable system been setup?
|
|
if (!mapvar_cvar) {
|
|
sprint(self,"\b[MAPVAR]\b System has not been setup yet!\n");
|
|
return;
|
|
}
|
|
|
|
// Reset impulse and initialize variables
|
|
self.impulse = 0;
|
|
loopbank = loopcell = 0;
|
|
|
|
dprint("\n\b[MAPVAR]\b Current System Values\n");
|
|
dprint("--------------------------------------\n");
|
|
while (loopbank < MAPV_BLCK) {
|
|
dprint("Bank "); dprint(ftos(loopbank)); dprint(" - ");
|
|
loopcell = 0; loopspace = 4;
|
|
while (loopcell < MAPV_BITS) {
|
|
loopval = query_mapvar((loopbank*MAPV_BITS)+loopcell);
|
|
dprint(ftos(loopval));
|
|
|
|
loopcell = loopcell+1;
|
|
if (loopcell == loopspace) {
|
|
dprint(" ");
|
|
loopspace = loopspace+4;
|
|
}
|
|
}
|
|
dprint("\n");
|
|
loopbank = loopbank+1;
|
|
}
|
|
dprint("--------------------------------------\n");
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() trigger_mapvar_base_use =
|
|
{
|
|
// Block entity state exceptions
|
|
if (self.estate & ESTATE_BLOCK) return;
|
|
// Is the trigger blocked? (trigger_once)
|
|
if (self.attack_finished > time) return;
|
|
|
|
// UPDATE : Map Variable
|
|
if (self.style == MAPV_UPDATE) {
|
|
self.lefty = self.cnt;
|
|
update_mapvar(self.count, self.cnt);
|
|
}
|
|
// TOGGLE : map variable
|
|
else if (self.style == MAPV_TOGGLE) {
|
|
self.lefty = query_mapvar(self.count);
|
|
self.lefty = 1 - self.lefty;
|
|
update_mapvar(self.count, self.lefty);
|
|
}
|
|
// QUERY : map variable
|
|
else {
|
|
self.lefty = query_mapvar(self.count);
|
|
}
|
|
|
|
// Check for On/Off target(s)
|
|
if (self.lefty == FALSE) {
|
|
if (self.target != "") trigger_strs(self.target, activator);
|
|
}
|
|
else {
|
|
if (self.target2 != "") trigger_strs(self.target2, activator);
|
|
}
|
|
|
|
// Check for switchable bmodel
|
|
if (self.noise != "") {
|
|
// Check if entity exists first
|
|
if (!self.oldenemy)
|
|
self.oldenemy = find(world, targetname, self.noise);
|
|
// Only work with Bmodel entities (usually aframes)
|
|
if (self.oldenemy.bsporigin) {
|
|
// Flashing (ON) is +0frame ; Static (OFF) is +aframe
|
|
if (self.lefty == TRUE) self.oldenemy.frame = 0;
|
|
else self.oldenemy.frame = 1;
|
|
}
|
|
}
|
|
|
|
// Check for fire once condition and wait timer
|
|
if (self.wait < 0) self.attack_finished = LARGE_TIMER;
|
|
else self.attack_finished = time + self.wait;
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() trigger_mapvar_base =
|
|
{
|
|
// Check for any missing keys
|
|
if (self.targetname == "") dprint("\b[MAPVAR]\b Missing targetname!\n");
|
|
// Remove any negative or fractions
|
|
self.count = fabs(rint(self.count));
|
|
|
|
// Check for upper variable range
|
|
if (self.count >= (MAPV_BLCK*MAPV_BITS))
|
|
self.count = (MAPV_BLCK*MAPV_BITS) - 1;
|
|
|
|
// Check for bitflag value range
|
|
if (self.cnt < FALSE || self.cnt > TRUE) self.cnt = FALSE;
|
|
|
|
// Setup Entity State functionality
|
|
if (self.targetname != "") self.use = entity_state_use;
|
|
self.estate_use = trigger_mapvar_base_use;
|
|
self.estate = ESTATE_ON;
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() trigger_mapvar_query =
|
|
{
|
|
self.classtype = CT_MAPVAR;
|
|
self.style = MAPV_QUERY;
|
|
trigger_mapvar_base();
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() trigger_mapvar_update =
|
|
{
|
|
self.classtype = CT_MAPVAR;
|
|
self.style = MAPV_UPDATE;
|
|
trigger_mapvar_base();
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() trigger_mapvar_toggle =
|
|
{
|
|
self.classtype = CT_MAPVAR;
|
|
self.style = MAPV_TOGGLE;
|
|
trigger_mapvar_base();
|
|
};
|
|
|
|
//======================================================================
|
|
/*QUAKED trigger_mapvar_multiple (0.5 0 0.5) ? x x x x x MONSTERS STARTOFF x Not_Easy Not_Normal Not_Hard Not_DM
|
|
Touch trigger target(s) based on mapvar
|
|
------- KEYS --------
|
|
targetname : trigger entity (works with entity state system)
|
|
count : Map Variable to check (range checks)
|
|
target : Map variable == 0 fire these target(s)
|
|
message : Map variable == 0 message to display
|
|
target2 : Map variable == 1 fire these target(s)
|
|
message2: Map variable == 1 message to display
|
|
health : Can be damaged instead of touched
|
|
wait : time between re-triggering
|
|
delay : delay before firing (after being triggered)
|
|
angle : Facing Direction for trigger to work, use "360" for angle 0.
|
|
sounds : 1=Secret,2=talk(def),3=switch,4=silent,5=custom,6=secret2
|
|
noise : custom sound to play when triggered
|
|
-------- SPAWNFLAGS --------
|
|
MONSTER : can be touched/triggered by monsters
|
|
STARTOFF : Requires trigger to activate
|
|
------- NOTES --------
|
|
Touch trigger target(s) based on mapvar
|
|
======================================================================*/
|
|
void() trigger_mapvar_multiple_fire =
|
|
{
|
|
if (self.attack_finished > time) return; // Trigger once?
|
|
|
|
// Find out map variable value
|
|
self.lefty = query_mapvar(self.count);
|
|
// Switch around target/message strings
|
|
if (self.lefty == FALSE) {
|
|
self.target = self.idle_sound;
|
|
self.message = self.idle_soundcom;
|
|
}
|
|
else {
|
|
self.target = self.idle_sound2;
|
|
self.message = self.idle_soundcom2;
|
|
}
|
|
|
|
// Play the sound ON the trigger, NOT the activator
|
|
if (self.noise != "") sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
|
|
|
|
// Original trigger_multiple activator behaviour
|
|
activator = self.bmodel_act;
|
|
SUB_UseTargets();
|
|
|
|
// Is the trigger repeatable?
|
|
if (self.wait > 0) {
|
|
self.attack_finished = time + self.wait;
|
|
self.nextthink = self.attack_finished;
|
|
self.think = self.estate_on;
|
|
}
|
|
else {
|
|
// TRIGGER_ONCE functionality
|
|
self.attack_finished = LARGE_TIMER;
|
|
self.estate_off();
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() trigger_mapvar_multiple =
|
|
{
|
|
if (check_bmodel_keys()) return; // Check for bmodel errors
|
|
|
|
// Remove excessive spawnflags not used
|
|
self.lefty = 0;
|
|
if (self.spawnflags & MAPV_MONSTERS) self.lefty = self.lefty | MAPV_MONSTERS;
|
|
if (self.spawnflags & ENT_STARTOFF) self.lefty = self.lefty | ENT_STARTOFF;
|
|
self.spawnflags = self.lefty;
|
|
|
|
// Remove any negative or fractions
|
|
self.count = fabs(rint(self.count));
|
|
|
|
// Check for upper variable range
|
|
if (self.count >= (MAPV_BLCK*MAPV_BITS))
|
|
self.count = (MAPV_BLCK*MAPV_BITS) - 1;
|
|
|
|
// Typical bmodel trigger setup
|
|
trigger_bmodel_sounds();
|
|
self.classtype = CT_MAPVAR;
|
|
InitTrigger ();
|
|
if (!self.wait) self.wait = 0.2;
|
|
|
|
// Save all entity for later
|
|
self.idle_sound = self.target;
|
|
self.idle_sound2 = self.target2;
|
|
self.idle_soundcom = self.message;
|
|
self.idle_soundcom2 = self.message2;
|
|
|
|
// Reset all strings to prevent SUB_UseTargets errors
|
|
self.target = ""; self.target2 = "";
|
|
self.message = ""; self.message2 = "";
|
|
|
|
// Setup Entity State functionality
|
|
self.estate_fire = trigger_mapvar_multiple_fire;
|
|
trigger_bmodel_setup();
|
|
}; |