- wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints
- wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache
- make
- - EXPECT=dc1bc3ac45188576a9651c6b7a1535a8
+ - EXPECT=e62d1a2375f0976ab12e2d980add29bd
- HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
| tee /dev/stderr
| grep '^:'
seta notification_WEAPON_VORTEX_MURDER "1" "Enable this multiple notification"
// MSG_CHOICE notifications (count = 28):
-seta notification_CHOICE_CTF_CAPTURE_BROKEN "1" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
+seta notification_CHOICE_CTF_CAPTURE_BROKEN "2" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
seta notification_CHOICE_CTF_CAPTURE_BROKEN_ALLOWED "2" "Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
-seta notification_CHOICE_CTF_CAPTURE_TIME "1" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
+seta notification_CHOICE_CTF_CAPTURE_TIME "2" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
seta notification_CHOICE_CTF_CAPTURE_TIME_ALLOWED "2" "Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
-seta notification_CHOICE_CTF_CAPTURE_UNBROKEN "1" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
+seta notification_CHOICE_CTF_CAPTURE_UNBROKEN "2" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
seta notification_CHOICE_CTF_CAPTURE_UNBROKEN_ALLOWED "2" "Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
seta notification_CHOICE_CTF_PICKUP_ENEMY "1" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
seta notification_CHOICE_CTF_PICKUP_ENEMY_ALLOWED "2" "Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
#define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT)
float autocvar_cl_viewmodel_scale;
+float autocvar_cl_viewmodel_alpha;
bool autocvar_cl_bobmodel;
float autocvar_cl_bobmodel_speed;
if(!this.activeweapon || !autocvar_r_drawviewmodel)
return;
int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
- float a = this.alpha;
- static bool wasinvehicle;
+ float a = ((autocvar_cl_viewmodel_alpha) ? bound(-1, autocvar_cl_viewmodel_alpha, this.m_alpha) : this.m_alpha);
bool invehicle = player_localentnum > maxclients;
if (invehicle) a = -1;
- else if (wasinvehicle) a = 1;
- wasinvehicle = invehicle;
Weapon wep = this.activeweapon;
int c = entcs_GetClientColors(current_player);
vector g = weaponentity_glowmod(wep, NULL, c, this);
this.fade_rate = 0;
}
- int myteam = ReadByte();
- this.team = myteam - 1;
+ int proj_team = ReadByte();
+ this.team = proj_team - 1;
if(teamplay)
{
- if(myteam)
+ if(proj_team)
this.colormap = (this.team) * 0x11; // note: team - 1 on server (client uses different numbers)
else
this.colormap = 0x00;
this.colormap |= BIT(10); // RENDER_COLORMAPPED
}
else
- this.colormap = myteam;
+ this.colormap = proj_team;
// TODO: projectiles use glowmaps for their color, not teams
#if 0
if(this.colormap > 0)
return vec3(e.anim_duckwalkbackright.x, t, ANIMPRIO_CROUCH);
case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
return vec3(e.anim_duckwalkbackleft.x, t, ANIMPRIO_CROUCH);
- default:
- return vec3(e.anim_duckidle.x, t, ANIMPRIO_CROUCH);
}
+ return vec3(e.anim_duckidle.x, t, ANIMPRIO_CROUCH);
}
else
{
return vec3(e.anim_backright.x, t, ANIMPRIO_ACTIVE);
case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
return vec3(e.anim_backleft.x, t, ANIMPRIO_ACTIVE);
- default:
- return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
}
+ return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
}
// can't get here
- return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
+ //return vec3(e.anim_idle.x, t, ANIMPRIO_IDLE);
}
void animdecide_setimplicitstate(entity e, float onground)
{
// adjust rating of our flag carrier depending on his health
head = head.tag_entity;
- float f = bound(0, (head.health + head.armorvalue) / 100, 2) - 1;
+ float f = bound(0, (GetResourceAmount(head, RESOURCE_HEALTH) + GetResourceAmount(head, RESOURCE_ARMOR)) / 100, 2) - 1;
ratingscale += ratingscale * f * 0.1;
}
navigation_routerating(this, head, ratingscale, 10000);
int WinningCondition_LMS()
{
entity first_player = NULL;
- int total_players = 0;
+ int totalplayers = 0;
FOREACH_CLIENT(IS_PLAYER(it), {
- if (!total_players)
+ if (!totalplayers)
first_player = it;
- ++total_players;
+ ++totalplayers;
});
- if (total_players)
+ if (totalplayers)
{
- if (total_players > 1)
+ if (totalplayers > 1)
{
// two or more active players - continue with the game
#pragma once
// TODO: find a better location for these?
-float total_players;
+int total_players;
// todo: accept the number of teams as a parameter
void GameRules_teams(bool value);
TC(Inventory, this);
WriteHeader(MSG_ENTITY, ENT_CLIENT_INVENTORY);
entity e = this.owner;
- if (IS_SPEC(e)) e = e.enemy;
+ if (IS_SPEC(e)) e = PS(e.enemy); // TODO: how can this *ever* be the case?
TC(Player, e);
Inventory data = e.inventory;
Inventory_Write(data);
{
Inventory inv = NEW(Inventory), bak = NEW(Inventory);
inv.inventory = bak;
- inv.drawonlytoclient = e;
+ inv.drawonlytoclient = IS_CLIENT(e) ? e : e.m_client;
Net_LinkEntity((inv.owner = e).inventory = inv, false, 0, Inventory_Send);
}
void Inventory_delete(entity e) { delete(e.inventory.inventory); delete(e.inventory); }
TC(Pickup, this);
bool b = Item_GiveTo(item, player);
if (b) {
- LOG_DEBUGF("entity %i picked up %s", player, this.m_name);
- player.inventory.inv_items[this.m_id]++;
- Inventory_update(player);
+ //LOG_DEBUGF("entity %i picked up %s", player, this.m_name);
+ entity store = IS_PLAYER(player) ? PS(player) : player;
+ store.inventory.inv_items[this.m_id]++;
+ Inventory_update(store);
}
return b;
}
if(fexists(strcat("scripts/", pFilename, ".arena")))
fputs(fh, "settemp_for_type all sv_q3acompat_machineshotgunswap 1\n");
+ if(fexists(strcat("scripts/", pFilename, ".defi")))
+ fputs(fh, "settemp_for_type all sv_vq3compat 1\n");
+
fputs(fh, "// optional: fog density red green blue alpha mindist maxdist\n");
fputs(fh, "// optional: settemp_for_type (all|gametypename) cvarname value\n");
fputs(fh, "// optional: clientsettemp_for_type (all|gametypename) cvarname value\n");
{
SetResourceAmountExplicit(this.owner, RESOURCE_HEALTH, this.owner.max_health);
this.owner.takedamage = DAMAGE_NO; // will be reset upon return
- door_use(this.owner, NULL, NULL);
+ door_use(this.owner, attacker, NULL);
}
}
#include <common/mapobjects/misc/corner.qc>
#include <common/mapobjects/misc/dynlight.qc>
#include <common/mapobjects/misc/follow.qc>
+#include <common/mapobjects/misc/keys.qc>
#include <common/mapobjects/misc/laser.qc>
#include <common/mapobjects/misc/teleport_dest.qc>
#include <common/mapobjects/misc/corner.qh>
#include <common/mapobjects/misc/dynlight.qh>
#include <common/mapobjects/misc/follow.qh>
+#include <common/mapobjects/misc/keys.qh>
#include <common/mapobjects/misc/laser.qh>
#include <common/mapobjects/misc/teleport_dest.qh>
--- /dev/null
+#include "keys.qh"
+
+#ifdef CSQC
+bool item_keys_usekey(entity l, entity p)
+{
+ int valid = (l.itemkeys & p.itemkeys); // TODO: itemkeys isn't networked or anything!
+ l.itemkeys &= ~valid; // only some of the needed keys were given
+ return valid != 0;
+}
+#endif
+
+#ifdef SVQC
+/*
+TODO:
+- add an unlock sound (here to trigger_keylock and to func_door)
+- display available keys on the HUD
+- make more tests
+- think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility
+- should keys have a trigger?
+*/
+
+bool item_keys_usekey(entity l, entity p)
+{
+ int valid = l.itemkeys & p.itemkeys;
+
+ if (!valid) {
+ // player has none of the needed keys
+ return false;
+ } else if (l.itemkeys == valid) {
+ // ALL needed keys were given
+ l.itemkeys = 0;
+ return true;
+ } else {
+ // only some of the needed keys were given
+ l.itemkeys &= ~valid;
+ return true;
+ }
+}
+
+string item_keys_keylist(float keylist) {
+ // no keys
+ if (!keylist)
+ return "";
+
+ // one key
+ if ((keylist & (keylist-1)) == 0)
+ return strcat("the ", item_keys_names[lowestbit(keylist)]);
+
+ string n = "";
+ int base = 0;
+ while (keylist) {
+ int l = lowestbit(keylist);
+ if (n)
+ n = strcat(n, ", the ", item_keys_names[base + l]);
+ else
+ n = strcat("the ", item_keys_names[base + l]);
+
+ keylist = bitshift(keylist, -(l + 1));
+ base+= l + 1;
+ }
+
+ return n;
+}
+
+
+/*
+================================
+item_key
+================================
+*/
+
+/**
+ * Key touch handler.
+ */
+void item_key_touch(entity this, entity toucher)
+{
+ if (!IS_PLAYER(toucher))
+ return;
+
+ // player already picked up this key
+ if (PS(toucher).itemkeys & this.itemkeys)
+ return;
+
+ PS(toucher).itemkeys |= this.itemkeys;
+ play2(toucher, this.noise);
+
+ centerprint(toucher, this.message);
+
+ string oldmsg = this.message;
+ this.message = "";
+ SUB_UseTargets(this, toucher, toucher); // TODO: should we be using toucher for the trigger here?
+ this.message = oldmsg;
+}
+
+/**
+ * Spawn a key with given model, key code and color.
+ */
+void spawn_item_key(entity this)
+{
+ precache_model(this.model);
+
+ if (this.spawnflags & 1) // FLOATING
+ this.noalign = 1;
+
+ if (this.noalign)
+ set_movetype(this, MOVETYPE_NONE);
+ else
+ set_movetype(this, MOVETYPE_TOSS);
+
+ precache_sound(this.noise);
+
+ this.mdl = this.model;
+ this.effects = EF_LOWPRECISION;
+ _setmodel(this, this.model);
+ //setsize(this, '-16 -16 -24', '16 16 32');
+ setorigin(this, this.origin + '0 0 32');
+ setsize(this, '-16 -16 -56', '16 16 0');
+ this.modelflags |= MF_ROTATE;
+ this.solid = SOLID_TRIGGER;
+
+ if (!this.noalign)
+ {
+ // first nudge it off the floor a little bit to avoid math errors
+ setorigin(this, this.origin + '0 0 1');
+ // note droptofloor returns false if stuck/or would fall too far
+ droptofloor(this);
+ }
+
+ settouch(this, item_key_touch);
+}
+
+
+/*QUAKED item_key (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
+A key entity.
+The itemkeys should contain one of the following key IDs:
+1 - GOLD key -
+2 - SILVER key
+4 - BRONZE key
+8 - RED keycard
+16 - BLUE keycard
+32 - GREEN keycard
+Custom keys:
+... - last key is 1<<23
+Keys with bigger Id than 32 don't have a default netname and model, if you use one of them, you MUST provide those.
+-----------KEYS------------
+colormod: color of the key (default: '.9 .9 .9').
+itemkeys: a key Id.
+message: message to print when player picks up this key.
+model: custom key model to use.
+netname: the display name of the key.
+noise: custom sound to play when player picks up the key.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+---------NOTES----------
+This is the only correct way to put keys on the map!
+
+itemkeys MUST always have exactly one bit set.
+*/
+spawnfunc(item_key)
+{
+ string _netname;
+ vector _colormod;
+
+ // reject this entity if more than one key was set!
+ if (this.itemkeys>0 && (this.itemkeys & (this.itemkeys-1)) != 0) {
+ objerror(this, "item_key.itemkeys must contain only 1 bit set specifying the key it represents!");
+ delete(this);
+ return;
+ }
+
+ // find default netname and colormod
+ switch(this.itemkeys) {
+ case BIT(0):
+ _netname = "GOLD key";
+ _colormod = '1 .9 0';
+ break;
+
+ case BIT(1):
+ _netname = "SILVER key";
+ _colormod = '.9 .9 .9';
+ break;
+
+ case BIT(2):
+ _netname = "BRONZE key";
+ _colormod = '.6 .25 0';
+ break;
+
+ case BIT(3):
+ _netname = "RED keycard";
+ _colormod = '.9 0 0';
+ break;
+
+ case BIT(4):
+ _netname = "BLUE keycard";
+ _colormod = '0 0 .9';
+ break;
+
+ case BIT(5):
+ _netname = "GREEN keycard";
+ _colormod = '0 .9 0';
+ break;
+
+ default:
+ _netname = "FLUFFY PINK keycard";
+ _colormod = '1 1 1';
+
+ if (this.netname == "") {
+ objerror(this, "item_key doesn't have a default name for this key and a custom one was not specified!");
+ delete(this);
+ return;
+ }
+ break;
+
+ }
+
+ // find default model
+ string _model = string_null;
+ if (this.itemkeys <= ITEM_KEY_BIT(2)) {
+ _model = "models/keys/key.md3";
+ } else if (this.itemkeys >= ITEM_KEY_BIT(3) && this.itemkeys <= ITEM_KEY_BIT(5)) {
+ _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model!
+ } else if (this.model == "") {
+ objerror(this, "item_key doesn't have a default model for this key and a custom one was not specified!");
+ delete(this);
+ return;
+ }
+
+ // set defailt netname
+ if (this.netname == "")
+ this.netname = _netname;
+
+ // set default colormod
+ if (!this.colormod)
+ this.colormod = _colormod;
+
+ // set default model
+ if (this.model == "")
+ this.model = _model;
+
+ // set default pickup message
+ if (this.message == "")
+ this.message = strzone(strcat("You've picked up the ", this.netname, "!"));
+
+ if (this.noise == "")
+ this.noise = strzone(SND(ITEMPICKUP));
+
+ // save the name for later
+ item_keys_names[lowestbit(this.itemkeys)] = this.netname;
+
+ // put the key on the map
+ spawn_item_key(this);
+}
+
+/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
+SILVER key.
+-----------KEYS------------
+colormod: color of the key (default: '.9 .9 .9').
+message: message to print when player picks up this key.
+model: custom model to use.
+noise: custom sound to play when player picks up the key.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+---------NOTES----------
+Don't use this entity on new maps! Use item_key instead.
+*/
+spawnfunc(item_key1)
+{
+ this.classname = "item_key";
+ this.itemkeys = ITEM_KEY_BIT(1);
+ spawnfunc_item_key(this);
+}
+
+/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
+GOLD key.
+-----------KEYS------------
+colormod: color of the key (default: '1 .9 0').
+message: message to print when player picks up this key.
+model: custom model to use.
+noise: custom sound to play when player picks up the key.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+---------NOTES----------
+Don't use this entity on new maps! Use item_key instead.
+*/
+spawnfunc(item_key2)
+{
+ this.classname = "item_key";
+ this.itemkeys = ITEM_KEY_BIT(0);
+ spawnfunc_item_key(this);
+}
+
+#endif
--- /dev/null
+#pragma once
+
+/**
+ * Returns the bit ID of a key
+ */
+#define ITEM_KEY_BIT(n) ( bitshift(1, n) )
+
+#define ITEM_KEY_MAX 24
+
+/**
+ * list of key names.
+ */
+#ifdef SVQC
+string item_keys_names[ITEM_KEY_MAX];
+
+/**
+ * Use keys from p on l.
+ * Returns true if any new keys were given, false otherwise.
+ */
+float item_keys_usekey(entity l, entity p);
+
+/**
+ * Returns a string with a comma separated list of key names, as specified in keylist.
+ */
+string item_keys_keylist(float keylist);
+#endif
void Ent_Wall_PreDraw(entity this)
{
+ float alph = this.alpha;
if (this.inactive)
{
- this.alpha = 0;
+ alph = 0;
}
else
{
vector org = getpropertyvec(VF_ORIGIN);
if(!checkpvs(org, this))
- this.alpha = 0;
+ alph = 0;
else if(this.fade_start || this.fade_end) {
vector offset = '0 0 0';
offset_z = this.fade_vertical_offset;
- float player_dist = vlen(org - this.origin - 0.5 * (this.mins + this.maxs) + offset);
+ vector player_dist_math = org - this.origin - 0.5 * (this.mins + this.maxs) + offset;
if (this.fade_end == this.fade_start)
{
- if (player_dist >= this.fade_start)
- this.alpha = 0;
+ if (vdist(player_dist_math, >=, this.fade_start))
+ alph = 0;
else
- this.alpha = 1;
+ alph = 1;
}
else
{
- this.alpha = (this.alpha_min + this.alpha_max * bound(0,
+ float player_dist = vlen(player_dist_math);
+ alph = (this.alpha_min + this.alpha_max * bound(0,
(this.fade_end - player_dist)
/ (this.fade_end - this.fade_start), 1)) / 100.0;
}
}
else
{
- this.alpha = 1;
+ alph = 1;
}
}
- if(this.alpha <= 0)
- this.drawmask = 0;
- else
- this.drawmask = MASK_NORMAL;
+ this.alpha = alph;
+ this.drawmask = (alph <= 0) ? 0 : MASK_NORMAL;
}
void Ent_Wall_Draw(entity this)
void counter_use(entity this, entity actor, entity trigger)
{
- this.count -= 1;
- if (this.count < 0)
+ entity store = this;
+ if(this.spawnflags & COUNTER_PER_PLAYER)
+ {
+ if(!IS_PLAYER(actor))
+ return;
+ store = actor;
+ }
+
+ store.counter_cnt += 1;
+ if (store.counter_cnt > this.count)
return;
bool doactivate = (this.spawnflags & COUNTER_FIRE_AT_COUNT);
- if (this.count == 0)
+ if (store.counter_cnt == this.count)
{
if(IS_PLAYER(actor) && !(this.spawnflags & SPAWNFLAG_NOMESSAGE))
Send_Notification(NOTIF_ONE, actor, MSG_CENTER, CENTER_SEQUENCE_COMPLETED);
{
if(IS_PLAYER(actor) && !(this.spawnflags & SPAWNFLAG_NOMESSAGE))
{
- if(this.count >= 4)
+ if((this.count - store.counter_cnt) >= 4)
Send_Notification(NOTIF_ONE, actor, MSG_CENTER, CENTER_SEQUENCE_COUNTER);
else
- Send_Notification(NOTIF_ONE, actor, MSG_CENTER, CENTER_SEQUENCE_COUNTER_FEWMORE, this.count);
+ Send_Notification(NOTIF_ONE, actor, MSG_CENTER, CENTER_SEQUENCE_COUNTER_FEWMORE, this.count - store.counter_cnt);
}
}
{
setthink(this, func_null);
this.nextthink = 0;
- this.count = this.cnt;
+ this.counter_cnt = 0;
}
/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage COUNTER_FIRE_AT_COUNT
{
if (!this.count)
this.count = 2;
- this.cnt = this.count;
+ this.counter_cnt = 0;
this.use = counter_use;
this.reset = counter_reset;
}
#pragma once
+#ifdef SVQC
+spawnfunc(trigger_counter);
+
+.float counter_cnt;
+#endif
const int COUNTER_FIRE_AT_COUNT = BIT(2);
+const int COUNTER_PER_PLAYER = BIT(3);
if (toucher.triggerhurttime < time)
{
EXACTTRIGGER_TOUCH(this, toucher);
- toucher.triggerhurttime = time + 1;
+ toucher.triggerhurttime = time + ((autocvar_sv_vq3compat && !(this.spawnflags & HURT_SLOW)) ? 0.1 : 1);
entity own;
own = this.enemy;
/*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ?
Any object touching this will be hurt
set dmg to damage amount
-default dmg = 1000
+default dmg = 10000
*/
.entity trigger_hurt_next;
entity trigger_hurt_last;
this.use = trigger_hurt_use;
this.enemy = world; // I hate you all
if (!this.dmg)
- this.dmg = 1000;
+ this.dmg = ((autocvar_sv_vq3compat) ? 5 : 10000);
if (this.message == "")
this.message = "was in the wrong place";
if (this.message2 == "")
#pragma once
+
+const int HURT_SLOW = BIT(4);
if (!isPushable(targ))
return false;
+ vector org = targ.origin;
+#ifdef SVQC
+ if(autocvar_sv_vq3compat)
+#elif defined(CSQC)
+ if(STAT(VQ3COMPAT))
+#endif
+ {
+ org.z += targ.mins_z;
+ org.z += 1; // off by 1!
+ }
+
if(this.enemy)
{
- targ.velocity = trigger_push_calculatevelocity(targ.origin, this.enemy, this.height, targ);
+ targ.velocity = trigger_push_calculatevelocity(org, this.enemy, this.height, targ);
}
else if(this.target && this.target != "")
{
else
RandomSelection_AddEnt(e, 1, 1);
}
- targ.velocity = trigger_push_calculatevelocity(targ.origin, RandomSelection_chosen_ent, this.height, targ);
+ targ.velocity = trigger_push_calculatevelocity(org, RandomSelection_chosen_ent, this.height, targ);
}
else
{
// check silver key
if(this.itemkeys)
- key_used = item_keys_usekey(this, toucher);
+ {
+#ifdef SVQC
+ entity store = PS(toucher);
+#elif defined(CSQC)
+ entity store = toucher;
+#endif
+ key_used = item_keys_usekey(this, store);
+ }
if(this.itemkeys)
{
#pragma once
-
-#ifdef CSQC
-bool item_keys_usekey(entity l, entity p)
-{
- int valid = (l.itemkeys & p.itemkeys); // TODO: itemkeys isn't networked or anything!
- l.itemkeys &= ~valid; // only some of the needed keys were given
- return valid != 0;
-}
-#endif
#include "triggers.qh"
-#ifdef SVQC
- #include <server/item_key.qh>
-#endif
void SUB_DontUseTargets(entity this, entity actor, entity trigger) { }
bool M_Spider_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
{
+ Weapon wep = WEP_SPIDER_ATTACK;
switch(attack_type)
{
- Weapon wep = WEP_SPIDER_ATTACK;
case MONSTER_ATTACK_MELEE:
{
wep.wr_think(wep, actor, weaponentity, 2);
}
.entity draggedby;
-.entity target2;
void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
{
#define SV_DAMAGETEXT_ALL() (autocvar_sv_damagetext >= 3)
MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) {
if (SV_DAMAGETEXT_DISABLED()) return;
- const entity attacker = M_ARGV(0, entity);
- const entity hit = M_ARGV(1, entity); if (hit == attacker) return;
- const float health = M_ARGV(2, float);
- const float armor = M_ARGV(3, float);
- const int deathtype = M_ARGV(5, int);
- const float potential_damage = M_ARGV(6, float);
+ entity attacker = M_ARGV(0, entity);
+ entity hit = M_ARGV(1, entity); if (hit == attacker) return;
+ float health = M_ARGV(2, float);
+ float armor = M_ARGV(3, float);
+ int deathtype = M_ARGV(5, int);
+ float potential_damage = M_ARGV(6, float);
if(DEATH_WEAPONOF(deathtype) == WEP_VAPORIZER) return;
FOREACH_CLIENT(IS_REAL_CLIENT(it), {
if (
void DynamicHandicap_UpdateHandicap()
{
float total_score = 0;
- float total_players = 0;
+ float totalplayers = 0;
FOREACH_CLIENT(IS_PLAYER(it),
{
total_score += PlayerScore_Get(it, SP_SCORE);
- ++total_players;
+ ++totalplayers;
});
- float mean_score = total_score / total_players;
+ float mean_score = total_score / totalplayers;
FOREACH_CLIENT(true,
{
float score = PlayerScore_Get(it, SP_SCORE);
}
if (fire & 1) // Primary attack
{
- if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(okshotgun, animtime)))
+ if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(okshotgun, refire)))
{
return;
}
#define A_ALWAYS 2
// MSG_CHOICE_NOTIFICATIONS
- MULTITEAM_CHOICE(CTF_CAPTURE_BROKEN, 4, N__NORMAL, A_ALWAYS, MSG_INFO, INFO_CTF_CAPTURE, INFO_CTF_CAPTURE_BROKEN)
- MULTITEAM_CHOICE(CTF_CAPTURE_TIME, 4, N__NORMAL, A_ALWAYS, MSG_INFO, INFO_CTF_CAPTURE, INFO_CTF_CAPTURE_TIME)
- MULTITEAM_CHOICE(CTF_CAPTURE_UNBROKEN, 4, N__NORMAL, A_ALWAYS, MSG_INFO, INFO_CTF_CAPTURE, INFO_CTF_CAPTURE_UNBROKEN)
+ MULTITEAM_CHOICE(CTF_CAPTURE_BROKEN, 4, N_VERBOSE, A_ALWAYS, MSG_INFO, INFO_CTF_CAPTURE, INFO_CTF_CAPTURE_BROKEN)
+ MULTITEAM_CHOICE(CTF_CAPTURE_TIME, 4, N_VERBOSE, A_ALWAYS, MSG_INFO, INFO_CTF_CAPTURE, INFO_CTF_CAPTURE_TIME)
+ MULTITEAM_CHOICE(CTF_CAPTURE_UNBROKEN, 4, N_VERBOSE, A_ALWAYS, MSG_INFO, INFO_CTF_CAPTURE, INFO_CTF_CAPTURE_UNBROKEN)
MULTITEAM_CHOICE(CTF_PICKUP_TEAM, 4, N__NORMAL, A_ALWAYS, MSG_CENTER, CENTER_CTF_PICKUP_TEAM, CENTER_CTF_PICKUP_TEAM_VERBOSE)
MSG_CHOICE_NOTIF(CTF_PICKUP_TEAM_NEUTRAL, N__NORMAL, A_ALWAYS, MSG_CENTER, CENTER_CTF_PICKUP_TEAM_NEUTRAL, CENTER_CTF_PICKUP_TEAM_VERBOSE_NEUTRAL)
MSG_CHOICE_NOTIF(CTF_PICKUP_ENEMY, N__NORMAL, A_ALWAYS, MSG_CENTER, CENTER_CTF_PICKUP_ENEMY, CENTER_CTF_PICKUP_ENEMY_VERBOSE)
if(GAMEPLAYFIX_EASIERWATERJUMP(this) && (this.flags & FL_WATERJUMP) && !(blocked & 8))
this.velocity = primal_velocity;
+ if(PHYS_WALLCLIP(this) && this.pm_time && !(this.flags & FL_WATERJUMP) && !(blocked & 8))
+ this.velocity = primal_velocity;
+
if(applygravity)
{
if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !IS_ONGROUND(this))
#define PHYS_JUMPSTEP(s) STAT(MOVEVARS_JUMPSTEP)
#define PHYS_WALLFRICTION(s) STAT(MOVEVARS_WALLFRICTION)
+#define PHYS_WALLCLIP(s) STAT(MOVEVARS_WALLCLIP)
+
#ifdef CSQC
.float bouncestop;
.float bouncefactor;
void set_movetype(entity this, int mt);
+.float pm_time;
+
.float move_movetype;
.float move_time;
//.vector move_origin;
vector start_origin = this.origin;
vector start_velocity = this.velocity;
+ if(PHYS_WALLCLIP(this) && this.pm_time)
+ {
+ if(dt >= this.pm_time || (this.flags & FL_WATERJUMP))
+ this.pm_time = 0;
+ else
+ this.pm_time -= dt;
+ }
+
int clip = _Movetype_FlyMove(this, dt, applygravity, stepnormal, GAMEPLAYFIX_STEPMULTIPLETIMES(this) ? PHYS_STEPHEIGHT(this) : 0);
if (GAMEPLAYFIX_DOWNTRACEONGROUND(this) && !(clip & 1))
// if the move did not hit the ground at any point, we're not on ground
if (!(clip & 1))
UNSET_ONGROUND(this);
+ else if(PHYS_WALLCLIP(this) && !this.groundentity && (PHYS_WALLCLIP(this) == 2 || start_velocity.z < -200)) // don't do landing time if we were just going down a slope
+ this.pm_time = 0.25;
_Movetype_CheckVelocity(this);
_Movetype_LinkEdict(this, true);
}
// move down
- vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT(this) + start_velocity.z * dt);
+ vector downmove = '0 0 0';
+ downmove.z = -PHYS_STEPHEIGHT(this) + start_velocity.z * dt;
_Movetype_PushEntity(this, downmove, true);
if(wasfreed(this))
return;
{
this._ps = NEW(PlayerState, this);
- Inventory_new(this);
+ Inventory_new(PS(this));
}
void PlayerState_detach(entity this)
if (ps.m_client != this) return; // don't own state, spectator
ps.ps_push(ps, this);
+ Inventory_delete(ps);
FOREACH_CLIENT(PS(it) == ps, { PS(it) = NULL; });
delete(ps);
-
- Inventory_delete(this);
}
void GetCvars(entity this, entity store, int);
#endif
REGISTER_STAT(SLICK_APPLYGRAVITY, bool, autocvar_sv_slick_applygravity)
+#ifdef SVQC
+bool autocvar_sv_vq3compat;
+#endif
+REGISTER_STAT(VQ3COMPAT, bool, autocvar_sv_vq3compat)
+
#ifdef SVQC
#include "physics/movetypes/movetypes.qh"
float warmup_limit;
REGISTER_STAT(MOVEVARS_AIRACCEL_QW, float)
REGISTER_STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, float)
REGISTER_STAT(MOVEVARS_SPECIALCOMMAND, bool)
+#ifdef SVQC
+int autocvar_sv_wallclip;
+#endif
+REGISTER_STAT(MOVEVARS_WALLCLIP, int, autocvar_sv_wallclip)
#ifdef CSQC
return -5;
// Cant touch this
+ if (GetResourceAmount(e_target, RESOURCE_HEALTH) <= 0)
+ return -6;
+ else if(STAT(FROZEN, e_target) > 0)
+ return -6;
+
+ // vehicle
if(IS_VEHICLE(e_target))
{
- if (e_target.vehicle_health <= 0)
- return -6;
-
if ((validate_flags & TFL_TARGETSELECT_VEHICLES) && !e_target.owner)
return -7;
}
- else if (GetResourceAmount(e_target, RESOURCE_HEALTH) <= 0)
- return -6;
- else if(STAT(FROZEN, e_target) > 0)
- return -6;
// player
if (IS_CLIENT(e_target))
vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string _tagname,
float _pichlimit_min, float _pichlimit_max,
- float _rotlimit_min, float _rotlimit_max, float _aimspeed)
+ float _rotlimit_min, float _rotlimit_max, float _aimspeed, float dt)
{
vector vtmp, vtag;
float ftmp;
vtmp = vectoangles(normalize(_target - vtag));
vtmp = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(_vehic.angles), AnglesTransform_FromAngles(vtmp))) - _turrret.angles;
vtmp = AnglesTransform_Normalize(vtmp, true);
- ftmp = _aimspeed * frametime;
+ ftmp = _aimspeed * dt;
vtmp_y = bound(-ftmp, vtmp_y, ftmp);
vtmp_x = bound(-ftmp, vtmp_x, ftmp);
_turrret.angles_y = bound(_rotlimit_min, _turrret.angles_y + vtmp_y, _rotlimit_max);
if(timer + rpause < time)
{
if(_healthscale)
- regen = regen * (this.vehicle_health / this.max_health);
+ regen = regen * (GetResourceAmount(this, RESOURCE_HEALTH) / this.max_health);
this.(regen_field) = min(this.(regen_field) + regen * delta_time, field_max);
}
}
+void vehicles_regen_resource(entity this, float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time, float _healthscale, int resource)
+{
+ float resource_amount = GetResourceAmount(this, resource);
+
+ if(resource_amount < field_max)
+ if(timer + rpause < time)
+ {
+ if(_healthscale)
+ regen = regen * (resource_amount / this.max_health);
+
+ SetResourceAmount(this, resource, min(resource_amount + regen * delta_time, field_max));
+
+ if(this.owner)
+ this.owner.(regen_field) = (GetResourceAmount(this, resource) / field_max) * 100;
+ }
+}
+
void shieldhit_think(entity this)
{
this.alpha -= 0.1;
void vehicles_painframe(entity this)
{
- int myhealth = ((this.owner) ? this.owner.vehicle_health : ((this.vehicle_health / this.max_health) * 100));
+ int myhealth = ((this.owner) ? this.owner.vehicle_health : ((GetResourceAmount(this, RESOURCE_HEALTH) / this.max_health) * 100));
if(myhealth <= 50)
if(this.pain_frame < time)
if(this.vehicle_shield < 0)
{
- this.vehicle_health -= fabs(this.vehicle_shield);
+ TakeResource(this, RESOURCE_HEALTH, fabs(this.vehicle_shield));
this.vehicle_shieldent.colormod = '2 0 0';
this.vehicle_shield = 0;
this.vehicle_shieldent.alpha = 0.75;
}
else
{
- this.vehicle_health -= damage;
+ TakeResource(this, RESOURCE_HEALTH, damage);
if(sound_allowed(MSG_BROADCAST, attacker))
spamsound (this, CH_PAIN, SND_ONS_HIT2, VOL_BASE, ATTEN_NORM); // FIXME: PLACEHOLDER
else
this.velocity += force;
- if(this.vehicle_health <= 0)
+ if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0)
{
if(this.owner)
if(this.vehicle_flags & VHF_DEATHEJECT)
bool vehicles_heal(entity targ, entity inflictor, float amount, float limit)
{
float true_limit = ((limit != RESOURCE_LIMIT_NONE) ? limit : targ.max_health);
- //if(GetResourceAmount(targ, RESOURCE_HEALTH) <= 0 || GetResourceAmount(targ, RESOURCE_HEALTH) >= true_limit)
- if(targ.vehicle_health <= 0 || targ.vehicle_health >= true_limit)
+ if(GetResourceAmount(targ, RESOURCE_HEALTH) <= 0 || GetResourceAmount(targ, RESOURCE_HEALTH) >= true_limit)
return false;
- targ.vehicle_health = min(targ.vehicle_health + amount, true_limit);
- //GiveResourceWithLimit(targ, RESOURCE_HEALTH, amount, true_limit);
- //if(targ.owner)
- //targ.owner.vehicle_health = (targ.vehicle_health / targ.max_health) * 100;
+ GiveResourceWithLimit(targ, RESOURCE_HEALTH, amount, true_limit);
+ if(targ.owner)
+ targ.owner.vehicle_health = (GetResourceAmount(targ, RESOURCE_HEALTH) / targ.max_health) * 100;
return true;
}
.entity gunner1;
.entity gunner2;
-.float vehicle_health = _STAT(VEHICLESTAT_HEALTH); /// If ent is player this is 0..100 indicating precentage of health left on vehicle. If ent is vehicle, this is the real health value.
+.float vehicle_health = _STAT(VEHICLESTAT_HEALTH); /// If ent is player this is 0..100 indicating precentage of health left on vehicle. Vehicle's value is the health resource
.float vehicle_energy = _STAT(VEHICLESTAT_ENERGY); /// If ent is player this is 0..100 indicating precentage of energy left on vehicle. If ent is vehicle, this is the real energy value.
.float vehicle_shield = _STAT(VEHICLESTAT_SHIELD); /// If ent is player this is 0..100 indicating precentage of shield left on vehicle. If ent is vehicle, this is the real shield value.
#define VEHICLE_UPDATE_PLAYER(ply,vehi,fld,vhname) \
ply.vehicle_##fld = (vehi.vehicle_##fld / autocvar_g_vehicle_##vhname##_##fld) * 100
+#define VEHICLE_UPDATE_PLAYER_RESOURCE(ply,vehi,fld,vhname,res) \
+ ply.vehicle_##fld = (GetResourceAmount(vehi, res) / autocvar_g_vehicle_##vhname##_##fld) * 100
+
.float vehicle_enter_delay; // prevent players jumping to and from vehicles instantly
void vehicles_exit(entity vehic, int eject);
float autocvar_g_vehicle_bumblebee_cannon_ammo_regen = 100;
float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause = 1;
-float autocvar_g_vehicle_bumblebee_cannon_lock = 0;
+float autocvar_g_vehicle_bumblebee_cannon_lock = 1;
-float autocvar_g_vehicle_bumblebee_cannon_turnspeed = 160;
+float autocvar_g_vehicle_bumblebee_cannon_turnspeed = 260;
float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down = 60;
float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up = 60;
float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in = 20;
if(autocvar_g_vehicle_bumblebee_cannon_lock)
{
- if(gun.lock_time < time)
+ if(gun.lock_time < time || IS_DEAD(gun.enemy) || STAT(FROZEN, gun.enemy))
gun.enemy = NULL;
if(trace_ent)
- if(trace_ent.move_movetype)
- if(trace_ent.takedamage)
- if(!IS_DEAD(trace_ent) && !STAT(FROZEN, trace_ent))
- {
- if(DIFF_TEAM(trace_ent, this))
- {
- gun.enemy = trace_ent;
- gun.lock_time = time + 5;
- }
- }
+ if(trace_ent.move_movetype)
+ if(trace_ent.takedamage)
+ if(!IS_DEAD(trace_ent) && !STAT(FROZEN, trace_ent))
+ {
+ if(teamplay)
+ {
+ if(DIFF_TEAM(trace_ent, this))
+ {
+ gun.enemy = trace_ent;
+ gun.lock_time = time + 2.5;
+ }
+ }
+ else
+ {
+ gun.enemy = trace_ent;
+ gun.lock_time = time + 0.5;
+ }
+ }
}
if(gun.enemy)
UpdateAuxiliaryXhair(this, ad, '1 0 1', 1);
vehicle_aimturret(vehic, trace_endpos, gun, "fire",
autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
- _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+ _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed, dt);
}
else
vehicle_aimturret(vehic, _ct, gun, "fire",
autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
- _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+ _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed, dt);
if(!forbidWeaponUse(this))
if(PHYS_INPUT_BUTTON_ATCK(this))
gun.attack_finished_single[0] = time + autocvar_g_vehicle_bumblebee_cannon_refire;
}
- VEHICLE_UPDATE_PLAYER(this, vehic, health, bumblebee);
+ VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, bumblebee, RESOURCE_HEALTH);
if(vehic.vehicle_flags & VHF_HASSHIELD)
VEHICLE_UPDATE_PLAYER(this, vehic, shield, bumblebee);
vehicles_regen(this, this.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, dt, true);
if(this.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(this, this.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, dt, false);
+ vehicles_regen_resource(this, this.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, dt, false, RESOURCE_HEALTH);
if(this.vehicle_flags & VHF_ENERGYREGEN)
vehicles_regen(this, this.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, dt, false);
vang = vehicle_aimturret(vehic, trace_endpos, vehic.gun3, "fire",
autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
- autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1, autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides, autocvar_g_vehicle_bumblebee_raygun_turnspeed);
+ autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1, autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides, autocvar_g_vehicle_bumblebee_raygun_turnspeed, dt);
if(!forbidWeaponUse(this))
if((PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * PHYS_INPUT_FRAMETIME || autocvar_g_vehicle_bumblebee_raygun == 0))
if(IS_VEHICLE(trace_ent))
{
- if(autocvar_g_vehicle_bumblebee_healgun_sps && trace_ent.vehicle_health <= trace_ent.max_health)
+ if(autocvar_g_vehicle_bumblebee_healgun_sps && GetResourceAmount(trace_ent, RESOURCE_HEALTH) <= trace_ent.max_health)
trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * dt, trace_ent.tur_head.max_health);
}
else if(IS_CLIENT(trace_ent))
}
*/
- VEHICLE_UPDATE_PLAYER(this, vehic, health, bumblebee);
+ VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, bumblebee, RESOURCE_HEALTH);
VEHICLE_UPDATE_PLAYER(this, vehic, energy, bumblebee);
this.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
if(!autocvar_g_vehicle_bumblebee_swim)
instance.dphitcontentsmask |= DPCONTENTS_LIQUIDSMASK;
- instance.vehicle_health = autocvar_g_vehicle_bumblebee_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_bumblebee_health);
instance.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
instance.solid = SOLID_BBOX;
set_movetype(instance, MOVETYPE_TOSS);
instance.vehicle_exit = bumblebee_exit;
instance.respawntime = autocvar_g_vehicle_bumblebee_respawntime;
- instance.vehicle_health = autocvar_g_vehicle_bumblebee_health;
- instance.max_health = instance.vehicle_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_bumblebee_health);
+ instance.max_health = GetResourceAmount(instance, RESOURCE_HEALTH);
instance.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
}
float hudAlpha = autocvar_hud_panel_fg_alpha;
float blinkValue = 0.55 + sin(time * 7) * 0.45;
vector tmpPos = '0 0 0';
- vector tmpSize = '1 1 1' * hud_fontsize;
+ vector tmpSize = hud_fontsize;
tmpPos.x = vehicleHud_Pos.x + vehicleHud_Size.x * (520/768);
if(!AuxiliaryXhair[1].draw2d)
float autocvar_g_vehicle_bumblebee_cannon_radius = 225;
float autocvar_g_vehicle_bumblebee_cannon_refire = 0.2;
float autocvar_g_vehicle_bumblebee_cannon_speed = 20000;
-float autocvar_g_vehicle_bumblebee_cannon_spread = 0.02;
+float autocvar_g_vehicle_bumblebee_cannon_spread = 0;
float autocvar_g_vehicle_bumblebee_cannon_force = -35;
#endif
vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, dt, true);
if(vehic.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, dt, false);
+ vehicles_regen_resource(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, dt, false, RESOURCE_HEALTH);
if(vehic.vehicle_flags & VHF_ENERGYREGEN)
vehicles_regen(vehic, vehic.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, dt, false);
- VEHICLE_UPDATE_PLAYER(player, vehic, health, racer);
+ VEHICLE_UPDATE_PLAYER_RESOURCE(player, vehic, health, racer, RESOURCE_HEALTH);
VEHICLE_UPDATE_PLAYER(player, vehic, energy, racer);
if(vehic.vehicle_flags & VHF_HASSHIELD)
{
#ifdef SVQC
set_movetype(instance, MOVETYPE_BOUNCE);
- instance.owner.vehicle_health = (instance.vehicle_health / autocvar_g_vehicle_racer_health) * 100;
+ instance.owner.vehicle_health = (GetResourceAmount(instance, RESOURCE_HEALTH) / autocvar_g_vehicle_racer_health) * 100;
instance.owner.vehicle_shield = (instance.vehicle_shield / autocvar_g_vehicle_racer_shield) * 100;
if(instance.owner.flagcarried)
setthink(instance, racer_think);
instance.nextthink = time;
- instance.vehicle_health = autocvar_g_vehicle_racer_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_racer_health);
instance.vehicle_shield = autocvar_g_vehicle_racer_shield;
set_movetype(instance, MOVETYPE_TOSS);
instance.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
instance.bouncestop = autocvar_g_vehicle_racer_bouncestop;
instance.damageforcescale = 0.5;
- instance.vehicle_health = autocvar_g_vehicle_racer_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_racer_health);
instance.vehicle_shield = autocvar_g_vehicle_racer_shield;
#endif
}
instance.vehicle_flags |= VHF_HEALTHREGEN;
instance.respawntime = autocvar_g_vehicle_racer_respawntime;
- instance.vehicle_health = autocvar_g_vehicle_racer_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_racer_health);
instance.vehicle_shield = autocvar_g_vehicle_racer_shield;
- instance.max_health = instance.vehicle_health;
+ instance.max_health = GetResourceAmount(instance, RESOURCE_HEALTH);
#endif
#ifdef CSQC
vehicle_aimturret(vehic, trace_endpos, vehic.gun1, "fire1",
autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1, autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
- autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed);
+ autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed, dt);
vehicle_aimturret(vehic, trace_endpos, vehic.gun2, "fire1",
autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1, autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
- autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed);
+ autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed, dt);
/*
ad = ad * 0.5;
vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, dt, true);
if(vehic.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false);
+ vehicles_regen_resource(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false, RESOURCE_HEALTH);
if(vehic.vehicle_flags & VHF_ENERGYREGEN)
vehicles_regen(vehic, vehic.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, dt, false);
}
- VEHICLE_UPDATE_PLAYER(this, vehic, health, raptor);
+ VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, raptor, RESOURCE_HEALTH);
VEHICLE_UPDATE_PLAYER(this, vehic, energy, raptor);
if(vehic.vehicle_flags & VHF_HASSHIELD)
VEHICLE_UPDATE_PLAYER(this, vehic, shield, raptor);
vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, dt, true);
if(vehic.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false);
+ vehicles_regen_resource(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, dt, false, RESOURCE_HEALTH);
if(vehic.vehicle_flags & VHF_ENERGYREGEN)
vehicles_regen(vehic, vehic.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, dt, false);
this.vehicle_reload2 = bound(0, vehic.bomb1.alpha * 100, 100);
this.vehicle_ammo2 = (this.vehicle_reload2 == 100) ? 100 : 0;
- VEHICLE_UPDATE_PLAYER(this, vehic, health, raptor);
+ VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, raptor, RESOURCE_HEALTH);
VEHICLE_UPDATE_PLAYER(this, vehic, energy, raptor);
if(vehic.vehicle_flags & VHF_HASSHIELD)
VEHICLE_UPDATE_PLAYER(this, vehic, shield, raptor);
instance.owner.PlayerPhysplug = raptor_takeoff;
set_movetype(instance, MOVETYPE_BOUNCEMISSILE);
instance.solid = SOLID_SLIDEBOX;
- instance.owner.vehicle_health = (instance.vehicle_health / autocvar_g_vehicle_raptor_health) * 100;
+ instance.owner.vehicle_health = (GetResourceAmount(instance, RESOURCE_HEALTH) / autocvar_g_vehicle_raptor_health) * 100;
instance.owner.vehicle_shield = (instance.vehicle_shield / autocvar_g_vehicle_raptor_shield) * 100;
instance.velocity = '0 0 1'; // nudge upwards so takeoff sequence can work
instance.tur_head.exteriormodeltoclient = instance.owner;
}
instance.frame = 0;
- instance.vehicle_health = autocvar_g_vehicle_raptor_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_raptor_health);
instance.vehicle_shield = autocvar_g_vehicle_raptor_shield;
set_movetype(instance, MOVETYPE_TOSS);
instance.solid = SOLID_SLIDEBOX;
instance.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
instance.bouncestop = autocvar_g_vehicle_raptor_bouncestop;
instance.damageforcescale = 0.25;
- instance.vehicle_health = autocvar_g_vehicle_raptor_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_raptor_health);
instance.vehicle_shield = autocvar_g_vehicle_raptor_shield;
}
METHOD(Raptor, vr_setup, void(Raptor thisveh, entity instance))
instance.vehicle_exit = raptor_exit;
instance.respawntime = autocvar_g_vehicle_raptor_respawntime;
- instance.vehicle_health = autocvar_g_vehicle_raptor_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_raptor_health);
instance.vehicle_shield = autocvar_g_vehicle_raptor_shield;
- instance.max_health = instance.vehicle_health;
+ instance.max_health = GetResourceAmount(instance, RESOURCE_HEALTH);
if(!autocvar_g_vehicle_raptor_swim)
instance.dphitcontentsmask |= DPCONTENTS_LIQUIDSMASK;
vehicles_regen(vehic, vehic.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, dt, true);
if(vehic.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, dt, false);
+ vehicles_regen_resource(vehic, vehic.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, dt, false, RESOURCE_HEALTH);
PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_ATCK2(this) = false;
//this.vehicle_ammo2 = vehic.tur_head.frame;
this.oldorigin = this.origin; // negate fall damage
this.velocity = vehic.velocity;
- VEHICLE_UPDATE_PLAYER(this, vehic, health, spiderbot);
+ VEHICLE_UPDATE_PLAYER_RESOURCE(this, vehic, health, spiderbot, RESOURCE_HEALTH);
if(vehic.vehicle_flags & VHF_HASSHIELD)
VEHICLE_UPDATE_PLAYER(this, vehic, shield, spiderbot);
STAT(VEHICLESTAT_W2MODE, instance) = SBRM_GUIDE;
set_movetype(instance, MOVETYPE_WALK);
CSQCVehicleSetup(instance.owner, 0);
- instance.owner.vehicle_health = (instance.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100;
+ instance.owner.vehicle_health = (GetResourceAmount(instance, RESOURCE_HEALTH) / autocvar_g_vehicle_spiderbot_health) * 100;
instance.owner.vehicle_shield = (instance.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100;
if(instance.owner.flagcarried)
setorigin(instance, instance.pos1 + '0 0 128');
instance.angles = instance.pos2;
instance.damageforcescale = 0.03;
- instance.vehicle_health = autocvar_g_vehicle_spiderbot_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_spiderbot_health);
instance.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
instance.PlayerPhysplug = spiderbot_frame;
instance.vehicle_flags |= VHF_HEALTHREGEN;
instance.respawntime = autocvar_g_vehicle_spiderbot_respawntime;
- instance.vehicle_health = autocvar_g_vehicle_spiderbot_health;
+ SetResourceAmountExplicit(instance, RESOURCE_HEALTH, autocvar_g_vehicle_spiderbot_health);
instance.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
- instance.max_health = instance.vehicle_health;
+ instance.max_health = GetResourceAmount(instance, RESOURCE_HEALTH);
instance.pushable = true; // spiderbot can use jumppads
}
METHOD(WeaponPickup, giveTo, bool(entity this, entity item, entity player))
{
bool b = Item_GiveTo(item, player);
- if (b) {
- LOG_TRACEF("entity %i picked up %s", player, this.m_name);
- }
+ //if (b) {
+ //LOG_TRACEF("entity %i picked up %s", player, this.m_name);
+ //}
return b;
}
#endif
\
PROP(false, m_alpha, WEPENT_SET_NORMAL, \
{ WriteByte(chan, rint(bound(-1, 254 * this.m_alpha, 254) - -1)); }, \
- { (viewmodels[this.m_wepent_slot]).alpha = (ReadByte() + -1) / 254; }) \
+ { (viewmodels[this.m_wepent_slot]).m_alpha = (ReadByte() + -1) / 254; }) \
\
PROP(false, vortex_charge, WEPENT_SET_NORMAL, \
{ WriteByte(chan, this.vortex_charge * 255); }, \
.Weapon switchingweapon;
.Weapon switchweapon;
+ .float m_alpha;
+
// only for Porto
.bool angles_held_status;
.vector angles_held;
/** Called once per CSQC_UpdateView() */
void CSQCPlayer_SetCamera()
{
- const vector v0 = ((intermission && !autocvar_cl_movement_intermissionrunning) ? '0 0 0' : pmove_vel); // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
- const float vh = PHYS_VIEWHEIGHT(NULL);
- const vector pl_viewofs = PHYS_PL_VIEWOFS(NULL);
- const vector pl_viewofs_crouch = PHYS_PL_CROUCH_VIEWOFS(NULL);
- const entity e = csqcplayer;
+ vector v0 = ((intermission && !autocvar_cl_movement_intermissionrunning) ? '0 0 0' : pmove_vel); // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
+ float vh = PHYS_VIEWHEIGHT(NULL);
+ vector pl_viewofs = PHYS_PL_VIEWOFS(NULL);
+ vector pl_viewofs_crouch = PHYS_PL_CROUCH_VIEWOFS(NULL);
+ entity e = csqcplayer;
if (e)
{
if (servercommandframe == 0 || clientcommandframe == 0)
}
else
{
- const int flg = e.iflags; e.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES);
+ int flg = e.iflags; e.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES);
InterpolateOrigin_Do(e);
e.iflags = flg;
if (csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
{
- const vector o = e.origin;
+ vector o = e.origin;
csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
CSQCPlayer_PredictTo(e, servercommandframe + 1, false);
CSQCPlayer_SetPredictionError(e.origin - o, e.velocity - v0, pmove_onground - IS_ONGROUND(e));
s = "";
for(int j = 0; j < n; ++j)
{
- FOREACH(Weapons, it != WEP_Null, {
- if(argv(j) == it.netname)
- s = cons_mid(s, " & ", it.m_name);
- });
+ Weapon wep = Weapons_fromstr(argv(j));
+ if(wep != WEP_Null)
+ {
+ s = cons_mid(s, " & ", wep.m_name);
+ }
}
s = sprintf(_("%s Arena"), s);
e.configureXonoticTextSliderValues(e);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Input packets/s:")));
- me.TD(me, 1, 2, e = makeXonoticSlider_T(20, 100, 5, "cl_netfps",
+ me.TD(me, 1, 2, e = makeXonoticSlider_T(30, 180, 5, "cl_netfps",
_("How many input packets to send to the server each second")));
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Server queries/s:")));
#include <server/handicap.qc>
#include <server/impulse.qc>
#include <server/ipban.qc>
-#include <server/item_key.qc>
#include <server/items.qc>
#include <server/mapvoting.qc>
#include <server/matrix.qc>
#include <server/handicap.qh>
#include <server/impulse.qh>
#include <server/ipban.qh>
-#include <server/item_key.qh>
#include <server/items.qh>
#include <server/mapvoting.qh>
#include <server/matrix.qh>
string autocvar_g_ban_sync_trusted_servers;
bool autocvar_g_ban_sync_trusted_servers_verify;
string autocvar_g_ban_sync_uri;
+bool autocvar_g_ban_telluser = true;
string autocvar_g_banned_list;
bool autocvar_g_banned_list_idmode;
bool autocvar_g_botclip_collisions;
//int player_limit = GetPlayerLimit(); // TODO: use this instead of maxclients!
int bots;
- // add/remove bots if needed to make sure there are at least
- // minplayers+bot_number, or remove all bots if no one is playing
// But don't remove bots immediately on level change, as the real players
// usually haven't rejoined yet
bots_would_leave = false;
bots = min(ceil(fabs(autocvar_bot_vs_human) * activerealplayers), maxclients - realplayers);
else if ((realplayers || autocvar_bot_join_empty || (currentbots > 0 && time < 5)))
{
- float realminplayers, minplayers;
- realminplayers = autocvar_minplayers;
- minplayers = max(0, floor(realminplayers));
+ int minplayers = max(0, floor(autocvar_minplayers));
+ int minbots = max(0, floor(autocvar_bot_number));
- float realminbots, minbots;
- realminbots = autocvar_bot_number;
- minbots = max(0, floor(realminbots));
+ // add bots to reach minplayers if needed
+ bots = max(minbots, minplayers - activerealplayers);
+ // cap bots to the max players allowed by the server
+ bots = min(bots, maxclients - realplayers);
- bots = min(max(minbots, minplayers - activerealplayers), maxclients - realplayers);
if(bots > minbots)
bots_would_leave = true;
}
#include "../common/wepent.qh"
#include <common/state.qh>
+#include "compat/quake3.qh"
+
#include <common/effects/qc/globalsound.qh>
#include "../common/mapobjects/func/conveyor.qh"
#include "../common/mapobjects/teleporters.qh"
#include "../common/mapobjects/target/spawnpoint.qh"
+#include <common/mapobjects/trigger/counter.qh>
#include "../common/vehicles/all.qh"
this.speedrunning = false;
+ this.counter_cnt = 0;
+ this.fragsfilter_cnt = 0;
+
target_voicescript_clear(this);
// reset fields the weapons may use
});
{
- string s = spot.target;
- spot.target = string_null;
+ //string s = spot.target;
+ //spot.target = string_null;
SUB_UseTargets(spot, this, NULL);
- spot.target = s;
+ //spot.target = s;
}
Unfreeze(this);
/** Client IP */
ATTRIB(Client, netaddress, string, this.netaddress);
ATTRIB(Client, playermodel, string, this.playermodel);
- ATTRIB(Client, playerskin, int, this.playerskin);
+ ATTRIB(Client, playerskin, string, this.playerskin);
/** fingerprint of CA key the player used to authenticate */
ATTRIB(Client, crypto_keyfp, string, this.crypto_keyfp);
#include <server/resources.qh>
#include <common/t_items.qh>
#include <common/mapobjects/triggers.qh>
+#include <common/mapobjects/trigger/counter.qh>
#include <common/weapons/_all.qh>
//***********************
InitializeEntity(this, target_give_init, INITPRIO_FINDTARGET);
}
+void score_use(entity this, entity actor, entity trigger)
+{
+ if(!IS_PLAYER(actor))
+ return;
+ actor.fragsfilter_cnt += this.count;
+}
+spawnfunc(target_score)
+{
+ if(!g_cts) { delete(this); return; }
+
+ if(!this.count)
+ this.count = 1;
+ this.use = score_use;
+}
+
+void fragsfilter_use(entity this, entity actor, entity trigger)
+{
+ if(!IS_PLAYER(actor))
+ return;
+ if(actor.fragsfilter_cnt >= this.frags)
+ SUB_UseTargets(this, actor, trigger);
+}
+spawnfunc(target_fragsFilter)
+{
+ if(!g_cts) { delete(this); return; }
+
+ if(!this.frags)
+ this.frags = 1;
+ this.use = fragsfilter_use;
+}
+
//spawnfunc(item_flight) /* handled by buffs mutator */
//spawnfunc(item_haste) /* handled by buffs mutator */
//spawnfunc(item_health) /* handled in t_quake.qc */
#pragma once
bool DoesQ3ARemoveThisEntity(entity this);
+
+.int fragsfilter_cnt;
}
e.fire_hitsound = true;
- if(!IS_INDEPENDENT_PLAYER(e))
- if(!STAT(FROZEN, e))
- FOREACH_CLIENT(IS_PLAYER(it) && it != e, {
- if(!IS_DEAD(it))
- if(!IS_INDEPENDENT_PLAYER(it))
+ if(!IS_INDEPENDENT_PLAYER(e) && !STAT(FROZEN, e))
+ {
+ IL_EACH(g_damagedbycontents, it.damagedbycontents && it != e,
+ {
+ if(!IS_DEAD(it) && it.takedamage && !IS_INDEPENDENT_PLAYER(it))
if(boxesoverlap(e.absmin, e.absmax, it.absmin, it.absmax))
{
t = autocvar_g_balance_firetransfer_time * (e.fire_endtime - time);
Fire_AddDamage(it, o, d, t, DEATH_FIRE.m_id);
}
});
+ }
+
}
void Fire_ApplyEffect(entity e)
// - for this timelimit_overtime needs to be >0 of course
// - also check the winning condition calculated in the previous frame and only add normal overtime
// again, if at the point at which timelimit would be extended again, still no winner was found
- if (!autocvar_g_campaign && (checkrules_overtimesadded >= 0) && (checkrules_overtimesadded < autocvar_timelimit_overtimes || autocvar_timelimit_overtimes < 0) && autocvar_timelimit_overtime && !(g_race && !g_race_qualifying))
+ if (!autocvar_g_campaign && checkrules_overtimesadded >= 0
+ && (checkrules_overtimesadded < autocvar_timelimit_overtimes || autocvar_timelimit_overtimes < 0)
+ && autocvar_timelimit_overtime && !(g_race && !g_race_qualifying))
{
return 1; // need to call InitiateOvertime later
}
{
++checkrules_overtimesadded;
//add one more overtime by simply extending the timelimit
- float tl;
- tl = autocvar_timelimit;
- tl += autocvar_timelimit_overtime;
- cvar_set("timelimit", ftos(tl));
-
+ cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime));
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60);
}
{
Team_SetTeamScore(Team_GetTeamFromIndex(i), 0);
}
-
+
FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
{
if (Team_IsValidTeam(it.team))
if (Ban_IsClientBanned(client, -1))
{
string s = sprintf("^1NOTE:^7 banned client %s just tried to enter\n", client.netaddress);
+ if(autocvar_g_ban_telluser)
+ sprint(client, "You are banned from this server.\n");
dropclient(client);
bprint(s);
return true;
+++ /dev/null
-#include "item_key.qh"
-
-#include "../common/mapobjects/subs.qh"
-#include <common/mapobjects/triggers.qh>
-#include "../common/monsters/_mod.qh"
-#include "../common/notifications/all.qh"
-#include "../common/util.qh"
-#include "../lib/warpzone/util_server.qh"
-
-/*
-TODO:
-- add an unlock sound (here to trigger_keylock and to func_door)
-- display available keys on the HUD
-- make more tests
-- think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility
-- should keys have a trigger?
-*/
-
-bool item_keys_usekey(entity l, entity p)
-{
- int valid = l.itemkeys & PS(p).itemkeys;
-
- if (!valid) {
- // player has none of the needed keys
- return false;
- } else if (l.itemkeys == valid) {
- // ALL needed keys were given
- l.itemkeys = 0;
- return true;
- } else {
- // only some of the needed keys were given
- l.itemkeys &= ~valid;
- return true;
- }
-}
-
-string item_keys_keylist(float keylist) {
- // no keys
- if (!keylist)
- return "";
-
- // one key
- if ((keylist & (keylist-1)) == 0)
- return strcat("the ", item_keys_names[lowestbit(keylist)]);
-
- string n = "";
- int base = 0;
- while (keylist) {
- int l = lowestbit(keylist);
- if (n)
- n = strcat(n, ", the ", item_keys_names[base + l]);
- else
- n = strcat("the ", item_keys_names[base + l]);
-
- keylist = bitshift(keylist, -(l + 1));
- base+= l + 1;
- }
-
- return n;
-}
-
-
-/*
-================================
-item_key
-================================
-*/
-
-/**
- * Key touch handler.
- */
-void item_key_touch(entity this, entity toucher)
-{
- if (!IS_PLAYER(toucher))
- return;
-
- // player already picked up this key
- if (PS(toucher).itemkeys & this.itemkeys)
- return;
-
- PS(toucher).itemkeys |= this.itemkeys;
- play2(toucher, this.noise);
-
- centerprint(toucher, this.message);
-
- string oldmsg = this.message;
- this.message = "";
- SUB_UseTargets(this, toucher, toucher); // TODO: should we be using toucher for the trigger here?
- this.message = oldmsg;
-}
-
-/**
- * Spawn a key with given model, key code and color.
- */
-void spawn_item_key(entity this)
-{
- precache_model(this.model);
-
- if (this.spawnflags & 1) // FLOATING
- this.noalign = 1;
-
- if (this.noalign)
- set_movetype(this, MOVETYPE_NONE);
- else
- set_movetype(this, MOVETYPE_TOSS);
-
- precache_sound(this.noise);
-
- this.mdl = this.model;
- this.effects = EF_LOWPRECISION;
- _setmodel(this, this.model);
- //setsize(this, '-16 -16 -24', '16 16 32');
- setorigin(this, this.origin + '0 0 32');
- setsize(this, '-16 -16 -56', '16 16 0');
- this.modelflags |= MF_ROTATE;
- this.solid = SOLID_TRIGGER;
-
- if (!this.noalign)
- {
- // first nudge it off the floor a little bit to avoid math errors
- setorigin(this, this.origin + '0 0 1');
- // note droptofloor returns false if stuck/or would fall too far
- droptofloor(this);
- }
-
- settouch(this, item_key_touch);
-}
-
-
-/*QUAKED item_key (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
-A key entity.
-The itemkeys should contain one of the following key IDs:
-1 - GOLD key -
-2 - SILVER key
-4 - BRONZE key
-8 - RED keycard
-16 - BLUE keycard
-32 - GREEN keycard
-Custom keys:
-... - last key is 1<<23
-Keys with bigger Id than 32 don't have a default netname and model, if you use one of them, you MUST provide those.
------------KEYS------------
-colormod: color of the key (default: '.9 .9 .9').
-itemkeys: a key Id.
-message: message to print when player picks up this key.
-model: custom key model to use.
-netname: the display name of the key.
-noise: custom sound to play when player picks up the key.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
----------NOTES----------
-This is the only correct way to put keys on the map!
-
-itemkeys MUST always have exactly one bit set.
-*/
-spawnfunc(item_key)
-{
- string _netname;
- vector _colormod;
-
- // reject this entity if more than one key was set!
- if (this.itemkeys>0 && (this.itemkeys & (this.itemkeys-1)) != 0) {
- objerror(this, "item_key.itemkeys must contain only 1 bit set specifying the key it represents!");
- delete(this);
- return;
- }
-
- // find default netname and colormod
- switch(this.itemkeys) {
- case BIT(0):
- _netname = "GOLD key";
- _colormod = '1 .9 0';
- break;
-
- case BIT(1):
- _netname = "SILVER key";
- _colormod = '.9 .9 .9';
- break;
-
- case BIT(2):
- _netname = "BRONZE key";
- _colormod = '.6 .25 0';
- break;
-
- case BIT(3):
- _netname = "RED keycard";
- _colormod = '.9 0 0';
- break;
-
- case BIT(4):
- _netname = "BLUE keycard";
- _colormod = '0 0 .9';
- break;
-
- case BIT(5):
- _netname = "GREEN keycard";
- _colormod = '0 .9 0';
- break;
-
- default:
- _netname = "FLUFFY PINK keycard";
- _colormod = '1 1 1';
-
- if (this.netname == "") {
- objerror(this, "item_key doesn't have a default name for this key and a custom one was not specified!");
- delete(this);
- return;
- }
- break;
-
- }
-
- // find default model
- string _model = string_null;
- if (this.itemkeys <= ITEM_KEY_BIT(2)) {
- _model = "models/keys/key.md3";
- } else if (this.itemkeys >= ITEM_KEY_BIT(3) && this.itemkeys <= ITEM_KEY_BIT(5)) {
- _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model!
- } else if (this.model == "") {
- objerror(this, "item_key doesn't have a default model for this key and a custom one was not specified!");
- delete(this);
- return;
- }
-
- // set defailt netname
- if (this.netname == "")
- this.netname = _netname;
-
- // set default colormod
- if (!this.colormod)
- this.colormod = _colormod;
-
- // set default model
- if (this.model == "")
- this.model = _model;
-
- // set default pickup message
- if (this.message == "")
- this.message = strzone(strcat("You've picked up the ", this.netname, "!"));
-
- if (this.noise == "")
- this.noise = strzone(SND(ITEMPICKUP));
-
- // save the name for later
- item_keys_names[lowestbit(this.itemkeys)] = this.netname;
-
- // put the key on the map
- spawn_item_key(this);
-}
-
-/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
-SILVER key.
------------KEYS------------
-colormod: color of the key (default: '.9 .9 .9').
-message: message to print when player picks up this key.
-model: custom model to use.
-noise: custom sound to play when player picks up the key.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
----------NOTES----------
-Don't use this entity on new maps! Use item_key instead.
-*/
-spawnfunc(item_key1)
-{
- this.classname = "item_key";
- this.itemkeys = ITEM_KEY_BIT(1);
- spawnfunc_item_key(this);
-}
-
-/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
-GOLD key.
------------KEYS------------
-colormod: color of the key (default: '1 .9 0').
-message: message to print when player picks up this key.
-model: custom model to use.
-noise: custom sound to play when player picks up the key.
--------- SPAWNFLAGS --------
-FLOATING: the item will float in air, instead of aligning to the floor by falling
----------NOTES----------
-Don't use this entity on new maps! Use item_key instead.
-*/
-spawnfunc(item_key2)
-{
- this.classname = "item_key";
- this.itemkeys = ITEM_KEY_BIT(0);
- spawnfunc_item_key(this);
-}
+++ /dev/null
-#pragma once
-
-/**
- * Returns the bit ID of a key
- */
-#define ITEM_KEY_BIT(n) ( bitshift(1, n) )
-
-#define ITEM_KEY_MAX 24
-
-/**
- * list of key names.
- */
-#ifdef SVQC
-string item_keys_names[ITEM_KEY_MAX];
-
-/**
- * Use keys from p on l.
- * Returns true if any new keys were given, false otherwise.
- */
-float item_keys_usekey(entity l, entity p);
-
-/**
- * Returns a string with a comma separated list of key names, as specified in keylist.
- */
-string item_keys_keylist(float keylist);
-#endif
for (i = 0; i < t; ++i)
{
s = argv(i);
- FOREACH(Weapons, it != WEP_Null, {
- if(it.netname == s)
- {
- g_weaponarena_weapons |= (it.m_wepset);
- g_weaponarena_list = strcat(g_weaponarena_list, it.m_name, " & ");
- break;
- }
- });
+ Weapon wep = Weapons_fromstr(s);
+ if(wep != WEP_Null)
+ {
+ g_weaponarena_weapons |= (wep.m_wepset);
+ g_weaponarena_list = strcat(g_weaponarena_list, wep.m_name, " & ");
+ }
}
g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3));
}
vector spawn_score = prio * '1 0 0' + shortest * '0 1 0';
// filter out spots for assault
- if(spot.target != "")
+ if(spot.target && spot.target != "")
{
int found = 0;
for(entity targ = findchain(targetname, spot.target); targ; targ = targ.chain)
TeamBalance_IsTeamAllowedInternal(balance, i))
{
TeamBalance_BanTeamsExcept(balance, i);
+ break;
}
- break;
}
balance.m_team_balance_state = TEAM_BALANCE_TEAMS_CHECKED;
return balance;
{
continue;
}
- int player_count = TeamBalanceTeam_GetNumberOfPlayers(team_);
+ int playercount = TeamBalanceTeam_GetNumberOfPlayers(team_);
if (smallest_team_index == 0)
{
smallest_team_index = i;
- smallest_team_player_count = player_count;
+ smallest_team_player_count = playercount;
}
- else if (player_count < smallest_team_player_count)
+ else if (playercount < smallest_team_player_count)
{
smallest_team_index = i;
- smallest_team_player_count = player_count;
+ smallest_team_player_count = playercount;
}
}
//PrintToChatAll(sprintf("Smallest team: %f", smallest_team_index));
{
continue;
}
- int player_count = TeamBalanceTeam_GetNumberOfPlayers(team_);
+ int playercount = TeamBalanceTeam_GetNumberOfPlayers(team_);
if (largest_team_index == 0)
{
largest_team_index = i;
- largest_team_player_count = player_count;
+ largest_team_player_count = playercount;
}
- else if (player_count > largest_team_player_count)
+ else if (playercount > largest_team_player_count)
{
largest_team_index = i;
- largest_team_player_count = player_count;
+ largest_team_player_count = playercount;
}
}
return largest_team_index;
for (int i = 1; i < t; ++i)
{
s = argv(i);
- FOREACH(Weapons, it != WEP_Null, {
- if(it.netname == s)
- {
- entity replacement = spawn();
- copyentity(this, replacement);
- replacement.m_isreplaced = true;
- weapon_defaultspawnfunc(replacement, it);
- break;
- }
- });
+ Weapon wep = Weapons_fromstr(s);
+ if(wep != WEP_Null)
+ {
+ entity replacement = spawn();
+ copyentity(this, replacement);
+ replacement.m_isreplaced = true;
+ weapon_defaultspawnfunc(replacement, wep);
+ }
}
}
if (t >= 1) // always the case!
{
s = argv(0);
- wpn = WEP_Null;
- FOREACH(Weapons, it != WEP_Null, {
- if(it.netname == s)
- {
- wpn = it;
- break;
- }
- });
+ wpn = Weapons_fromstr(s);
}
if (wpn == WEP_Null)
{
-electro
-{
- dpreflectcube cubemaps/default/sky
- {
- map textures/electro.tga
- rgbgen lightingDiffuse
- }
-}
nexgun
{
dpreflectcube cubemaps/default/sky
seta cl_movement_errorcompensation 1 "try to compensate for prediction errors and reduce perceived lag"
seta cl_movement_intermissionrunning 0 "keep velocity after the match ends, players may appear to continue running while stationary"
+seta cl_viewmodel_alpha 0 "Maximum transparency of the view model, set to 0 to disable"
+
set debugdraw 0
set debugdraw_filter ""
set debugdraw_filterout ""
// server settings
hostname "Xonotic $g_xonoticversion Server"
set sv_mapchange_delay 5
-set minplayers 0 "number of players playing at the same time (if not enough real players are there the remaining slots are filled with bots)"
+set minplayers 0 "fill server with bots to reach this number of players (if bot_number is not enough)"
// restart server if all players hit "ready"-button
set sv_ready_restart 0 "allow a map to be restarted once all players pressed the \"ready\" button"
set g_ban_default_bantime 5400 "90 minutes"
set g_ban_default_masksize 3 "masksize 0 means banning by UID only, 1 means banning by /8 (IPv6: /32) network, 2 means banning by /16 (IPv6: /48) network, 3 means banning by /24 (IPv6: /56) network, 4 means banning by single IP (IPv6: /64 network)"
+set g_ban_telluser 1 "notify the banned player about it when they try to join"
set g_banned_list "" "format: IP remainingtime IP remainingtime ..."
set g_banned_list_idmode "1" "when set, the IP banning system always uses the ID over the IP address (so a user in a banned IP range can connect if they have a valid signed ID)"
sv_gameplayfix_nogravityonground 1
set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping machinegun and shotgun (for Q3A map compatibility in mapinfo files)"
+set sv_vq3compat 0 "toggle for some compatibility hacks (for VQ3 and CPM map compatibility in mapinfo files)"
set g_movement_highspeed 1 "movement speed modification factor (only changes movement when above maxspeed)"