Merge branch 'master' into Mario/duel
authorMario <zacjardine@y7mail.com>
Fri, 21 Sep 2018 01:57:08 +0000 (11:57 +1000)
committerMario <zacjardine@y7mail.com>
Fri, 21 Sep 2018 01:57:08 +0000 (11:57 +1000)
70 files changed:
.gitlab-ci.yml
notifications.cfg
qcsrc/client/view.qc
qcsrc/client/weapons/projectile.qc
qcsrc/common/animdecide.qc
qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc
qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc
qcsrc/common/gamemodes/sv_rules.qh
qcsrc/common/items/inventory.qh
qcsrc/common/items/item/pickup.qc
qcsrc/common/mapinfo.qc
qcsrc/common/mapobjects/func/door.qc
qcsrc/common/mapobjects/misc/_mod.inc
qcsrc/common/mapobjects/misc/_mod.qh
qcsrc/common/mapobjects/misc/keys.qc [new file with mode: 0644]
qcsrc/common/mapobjects/misc/keys.qh [new file with mode: 0644]
qcsrc/common/mapobjects/models.qc
qcsrc/common/mapobjects/trigger/counter.qc
qcsrc/common/mapobjects/trigger/counter.qh
qcsrc/common/mapobjects/trigger/hurt.qc
qcsrc/common/mapobjects/trigger/hurt.qh
qcsrc/common/mapobjects/trigger/jumppads.qc
qcsrc/common/mapobjects/trigger/keylock.qc
qcsrc/common/mapobjects/trigger/keylock.qh
qcsrc/common/mapobjects/triggers.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc
qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc
qcsrc/common/mutators/mutator/overkill/okshotgun.qc
qcsrc/common/notifications/all.inc
qcsrc/common/physics/movetypes/movetypes.qc
qcsrc/common/physics/movetypes/movetypes.qh
qcsrc/common/physics/movetypes/walk.qc
qcsrc/common/state.qc
qcsrc/common/stats.qh
qcsrc/common/turrets/sv_turrets.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/sv_vehicles.qh
qcsrc/common/vehicles/vehicle/bumblebee.qc
qcsrc/common/vehicles/vehicle/bumblebee_weapons.qh
qcsrc/common/vehicles/vehicle/racer.qc
qcsrc/common/vehicles/vehicle/raptor.qc
qcsrc/common/vehicles/vehicle/spiderbot.qc
qcsrc/common/weapons/weapon.qh
qcsrc/common/wepent.qc
qcsrc/common/wepent.qh
qcsrc/lib/csqcmodel/cl_player.qc
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/menu/xonotic/dialog_settings_misc.qc
qcsrc/server/_mod.inc
qcsrc/server/_mod.qh
qcsrc/server/autocvars.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/compat/quake3.qc
qcsrc/server/compat/quake3.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/ipban.qc
qcsrc/server/item_key.qc [deleted file]
qcsrc/server/item_key.qh [deleted file]
qcsrc/server/miscfunctions.qc
qcsrc/server/spawnpoints.qc
qcsrc/server/teamplay.qc
qcsrc/server/weapons/spawning.qc
scripts/weapons.shader
xonotic-client.cfg
xonotic-server.cfg

index 9423d5d5dc081806a1dd2887200972f5ae5de2cd..f960751ca51d8b790ce2efefcea7944912998478 100644 (file)
@@ -29,7 +29,7 @@ test_sv_game:
     - 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 '^:'
index dc50883e0df2b5b0bfcc10211b55cddc32b705df..07423e3aac74c1034b1587c1b69febcd78eae0d3 100644 (file)
@@ -693,11 +693,11 @@ seta notification_WEAPON_VAPORIZER_MURDER "1" "Enable this multiple notification
 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"
index e873f64535bd40ca74bb8126e882c92f7085fe64..ff9b47cbcdaa97fb2c7d735bc96167d09b02298b 100644 (file)
@@ -48,6 +48,7 @@
 #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;
@@ -297,12 +298,9 @@ void viewmodel_draw(entity this)
        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);
index f4871e7fc6194803adf7fa2a8b9ec1276abc06c3..067c0badb7da09a184c192daf1841d47c782da81 100644 (file)
@@ -265,19 +265,19 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
                        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)
index b53a9ba0e9cbf6123d7438736785e8206200358a..69fe458269845c7e0acf7b3eaa17c3008cd5581d 100644 (file)
@@ -210,9 +210,8 @@ vector animdecide_getloweranim(entity e)
                                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
        {
@@ -236,12 +235,11 @@ vector animdecide_getloweranim(entity e)
                                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)
index efbbf94e72aceee1716ad7d50f9ad49edc6a66b7..2696a4e87892d4dca5dbc3b688d91f0b4bf85059 100644 (file)
@@ -1519,7 +1519,7 @@ void havocbot_goalrating_ctf_enemyflag(entity this, float ratingscale)
                {
                        // 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);
index ffbecf1b3df6abcb68c558b4e1c9336713225328..493320ccebc695ac5e9a3b9276f8166e6587e844 100644 (file)
@@ -36,16 +36,16 @@ void ClearWinners();
 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
 
index ca1b6f8e74649e80c2b1ebe8c180871c00cef75e..f8950684b4967eabaa9990de93a7e53746d8f0cc 100644 (file)
@@ -1,7 +1,7 @@
 #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);
index 9075c0912ed2a5044ba8e7b80b299a05723f31ba..ba824f40b41c14c470a214c33eeb0bd6e9064c4d 100644 (file)
@@ -107,7 +107,7 @@ bool Inventory_Send(Inventory this, Client to, int sf)
     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);
@@ -118,7 +118,7 @@ void Inventory_new(entity e)
 {
     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); }
index b5944fc0a3def7d7235f09bfc66e6ad33f2fb11e..a3c2d779edcde089ac3d4f7e142693de8e47070b 100644 (file)
@@ -11,9 +11,10 @@ METHOD(Pickup, giveTo, bool(Pickup this, entity item, entity player))
     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;
 }
index f5a0f666bdb57e3d8de103fe21b032aaefd53121..8d8884f21ddd09cb06ec94da5bb3dad95884d42e 100644 (file)
@@ -854,6 +854,9 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                        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");
index 8d40a377be081fbc583f3adef2486a129530d694..b7418298cbe7f05d45392770e5e2b3a9ed7bb4b9 100644 (file)
@@ -277,7 +277,7 @@ void door_damage(entity this, entity inflictor, entity attacker, float damage, i
        {
                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);
        }
 }
 
index 498f6c521e941c861d7049855699324bfd502666..c7f1619ad54faba790ac59e5533974e7d1e7a495 100644 (file)
@@ -2,5 +2,6 @@
 #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>
index 3415919f8993799be9acc23fdb1c16a54a6508ef..617db807b9c1f3d68e6e1209bcff3e7dc0afcd17 100644 (file)
@@ -2,5 +2,6 @@
 #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>
diff --git a/qcsrc/common/mapobjects/misc/keys.qc b/qcsrc/common/mapobjects/misc/keys.qc
new file mode 100644 (file)
index 0000000..2c85742
--- /dev/null
@@ -0,0 +1,292 @@
+#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
diff --git a/qcsrc/common/mapobjects/misc/keys.qh b/qcsrc/common/mapobjects/misc/keys.qh
new file mode 100644 (file)
index 0000000..50be5f8
--- /dev/null
@@ -0,0 +1,26 @@
+#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
index 92ff464b71016951d4f675e0c667b11429b5e13f..4f07409b10db1262a1fc992705a9a5c4361d81df 100644 (file)
@@ -199,42 +199,42 @@ spawnfunc(func_clientwall)        { G_CLIENTMODEL_INIT(this, SOLID_BSP) } // bru
 
 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)
index 4c89c4c27ed20efc86f73a678c615d68aa82673b..9156439f99e3bf19bb9bdc8425efe1fdcd06d53d 100644 (file)
@@ -4,13 +4,21 @@ void counter_reset(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);
@@ -27,10 +35,10 @@ void counter_use(entity this, entity actor, entity trigger)
        {
                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);
                }
        }
 
@@ -42,7 +50,7 @@ void counter_reset(entity this)
 {
        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
@@ -59,8 +67,8 @@ spawnfunc(trigger_counter)
 {
        if (!this.count)
                this.count = 2;
-       this.cnt = this.count;
 
+       this.counter_cnt = 0;
        this.use = counter_use;
        this.reset = counter_reset;
 }
index 394d15472cdbc68f289b9476ec00311e6dd22e09..d36bd0293cc933ead43f3e2248b46d157cdc91c3 100644 (file)
@@ -1,4 +1,10 @@
 #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);
index 966e0cfb0fe6657287ee8135c9f9411f732de18d..ccdf2c7d0b96a291086be949e2c53db8180b725d 100644 (file)
@@ -25,7 +25,7 @@ void trigger_hurt_touch(entity this, entity toucher)
                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;
@@ -53,7 +53,7 @@ void trigger_hurt_touch(entity this, entity toucher)
 /*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;
@@ -66,7 +66,7 @@ spawnfunc(trigger_hurt)
        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 == "")
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..e992154aa97fd6a76cd6d7fc6d856ebb356eda4a 100644 (file)
@@ -1 +1,3 @@
 #pragma once
+
+const int HURT_SLOW = BIT(4);
index 5ffdf2d1066085d9bd47fd1dd5d541af179b4671..ca1faeaf93c2ddd97e8c3ef052c3d770122cde26 100644 (file)
@@ -133,9 +133,20 @@ bool jumppad_push(entity this, entity targ)
        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 != "")
        {
@@ -148,7 +159,7 @@ bool jumppad_push(entity this, entity targ)
                        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
        {
index 67db14421662c2d0c40483b328ee3dd30ee6babe..f7ecd7c1f1ab8c5c0e3afd1e202085c2e27fd460 100644 (file)
@@ -30,7 +30,14 @@ void trigger_keylock_touch(entity this, entity toucher)
 
        // 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)
        {
index 904c3fa3d4a7404d5d4c0535fbc59858b2d6cc42..6f70f09beec2219624baeca92e2cd7deaa104fb4 100644 (file)
@@ -1,10 +1 @@
 #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
index c7ed6643de207b68d1dad094d9673ac75955f85a..6a20959997b34439e24d3fc7ceae7cbef35cb1fa 100644 (file)
@@ -1,7 +1,4 @@
 #include "triggers.qh"
-#ifdef SVQC
-       #include <server/item_key.qh>
-#endif
 
 void SUB_DontUseTargets(entity this, entity actor, entity trigger) { }
 
index 5e2cc0513851594d70a64167656be7196135500d..d847cf4e6cd2942494bb8beeb61d45abae40ad81 100644 (file)
@@ -168,9 +168,9 @@ void M_Spider_Attack_Web(entity this)
 
 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);
index 84355c7f3530ffddcf3dccde86781d487c7fd717..f30c5974a0ba6d1085fc57e576e7de66404aee92 100644 (file)
@@ -695,7 +695,6 @@ void Monster_CalculateVelocity(entity this, vector to, vector from, float turnra
 }
 
 .entity draggedby;
-.entity target2;
 
 void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
 {
index d9eacaae0c4e7a1cf2821d4574bb255a572c3bd5..0e0aa13fd0404412f13e612743d648bc1d436cca 100644 (file)
@@ -10,12 +10,12 @@ REGISTER_MUTATOR(damagetext, true);
 #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 (
index d5d3ba40f8ee233127078a6e4ff735d855f9f05a..4cfc0dd23779d4f5babee08a864b2fcce14dfdcd 100644 (file)
@@ -32,13 +32,13 @@ float DynamicHandicap_ClampHandicap(float handicap);
 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);
index 2f1651776fdab25a67b98a42b0f9e386b44805ea..d8c79e3f2e1e20fae5f4048ca6d35e3b58b0b696 100644 (file)
@@ -45,7 +45,7 @@ METHOD(OverkillShotgun, wr_think, void(entity thiswep, entity actor, .entity wea
        }
        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;
                }
index 7cb218412f8897dec276c561b06ce5bbd0b188bf..1b93cbf35986f4e62cdb127486095f8cd5f55b89 100644 (file)
 #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)
index 9ac3e4299901db21051d4ea2f206fe8636bbfa30..e518fe21027fa5089623adf331c4ecabae65607d 100644 (file)
@@ -232,6 +232,9 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
        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))
index 85912ee1c33f915ebdf59f907c616ef2f571c4f3..20f9adba1076a7b3499f60b0ed9096ec41f0d6d2 100644 (file)
@@ -26,6 +26,8 @@ const int WATERLEVEL_SUBMERGED = 3;
 #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;
@@ -55,6 +57,8 @@ const int WATERLEVEL_SUBMERGED = 3;
 
 void set_movetype(entity this, int mt);
 
+.float pm_time;
+
 .float move_movetype;
 .float move_time;
 //.vector move_origin;
index c20e82e8342825a9282142d288281ceffea2583d..6e4c548d6cd8aecdd2ced19a27d7f31b406524bf 100644 (file)
@@ -20,6 +20,14 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
        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))
@@ -45,6 +53,8 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
        // 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);
@@ -144,7 +154,8 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
        }
 
        // 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;
index 772dbccbd58d870137b69ab4143fc053e3b02e81..2e3a262a59e9662c2456e77a7277f2cb9bd9acef 100644 (file)
@@ -7,7 +7,7 @@ void PlayerState_attach(entity this)
 {
        this._ps = NEW(PlayerState, this);
 
-       Inventory_new(this);
+       Inventory_new(PS(this));
 }
 
 void PlayerState_detach(entity this)
@@ -18,11 +18,10 @@ 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);
index 9b8f04041780fd55f707331540c74ab99b0e8e88..cf51ea66b3ebf7b24d86c16c89756347fa5bca0c 100644 (file)
@@ -301,6 +301,11 @@ bool autocvar_sv_slick_applygravity;
 #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;
@@ -360,6 +365,10 @@ REGISTER_STAT(MOVEVARS_STEPHEIGHT, float, autocvar_sv_stepheight)
 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
index d3994fd8369436f20024506b1c71ba8880e149bf..4962ddbe6ed6b414623ee595f632cffc742c4b6a 100644 (file)
@@ -731,18 +731,17 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl
                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))
index 716dfe8d0c130225041502345a182873aa7c111f..2f5e8e46bf234d50efeb7e9a3670bf7466955823 100644 (file)
@@ -385,7 +385,7 @@ bool vehicle_addplayerslot( entity _owner,
 
 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;
@@ -393,7 +393,7 @@ vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string
        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);
@@ -587,7 +587,7 @@ void vehicles_regen(entity this, float timer, .float regen_field, float field_ma
        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);
 
@@ -596,6 +596,23 @@ void vehicles_regen(entity this, float timer, .float regen_field, float field_ma
        }
 }
 
+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;
@@ -613,7 +630,7 @@ void shieldhit_think(entity this)
 
 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)
@@ -684,7 +701,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag
 
                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;
@@ -699,7 +716,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag
        }
        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
@@ -710,7 +727,7 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag
        else
                this.velocity += force;
 
-       if(this.vehicle_health <= 0)
+       if(GetResourceAmount(this, RESOURCE_HEALTH) <= 0)
        {
                if(this.owner)
                        if(this.vehicle_flags & VHF_DEATHEJECT)
@@ -730,14 +747,12 @@ void vehicles_damage(entity this, entity inflictor, entity attacker, float damag
 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;
 }
 
index 0cc9da56ea11a57779850fc85f1bdd53ca0864e1..a1f23c1dfcc1b95522a3300296737dc4a927b026 100644 (file)
@@ -45,7 +45,7 @@ float autocvar_g_vehicles_weapon_damagerate = 2;
 .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.
 
@@ -99,6 +99,9 @@ float vehicles_exit_running;
 #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);
index c340d947035617492da6d224bbede286baf8e7be..84f5e144bfa6cb257ef272a97822c99fd8eb2aa5 100644 (file)
@@ -33,9 +33,9 @@ float autocvar_g_vehicle_bumblebee_cannon_ammo = 100;
 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;
@@ -105,20 +105,28 @@ bool bumblebee_gunner_frame(entity this, float dt)
 
        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)
@@ -141,13 +149,13 @@ bool bumblebee_gunner_frame(entity this, float dt)
                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))
@@ -160,7 +168,7 @@ bool bumblebee_gunner_frame(entity this, float dt)
                                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);
@@ -389,7 +397,7 @@ void bumblebee_regen(entity this, float dt)
                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);
@@ -521,7 +529,7 @@ bool bumblebee_pilot_frame(entity this, float dt)
 
        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))
@@ -555,7 +563,7 @@ bool bumblebee_pilot_frame(entity this, float dt)
 
                                                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))
@@ -584,7 +592,7 @@ bool bumblebee_pilot_frame(entity this, float dt)
        }
        */
 
-       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;
@@ -879,7 +887,7 @@ METHOD(Bumblebee, vr_spawn, void(Bumblebee thisveh, entity instance))
     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);
@@ -906,8 +914,8 @@ METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh, entity instance))
 
     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;
 }
 
@@ -930,7 +938,7 @@ METHOD(Bumblebee, vr_hud, void(Bumblebee thisveh))
     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)
index e9c5bf41d002167c5f3b74b17d99de8fad0ad60a..f6909fb42a2100527a5ec668d34fb8010b1d1a87 100644 (file)
@@ -8,7 +8,7 @@ float autocvar_g_vehicle_bumblebee_cannon_damage = 60;
 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
 
index 18e13bcbbe68d3f23bc558dad7b0e0f9427c4d2b..c7f7af8ac6efa82854bca37985be91fb85afabe2 100644 (file)
@@ -359,12 +359,12 @@ bool racer_frame(entity this, float dt)
                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)
@@ -514,7 +514,7 @@ METHOD(Racer, vr_enter, void(Racer thisveh, entity instance))
 {
 #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)
@@ -544,7 +544,7 @@ METHOD(Racer, vr_spawn, void(Racer thisveh, entity instance))
 
     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);
@@ -557,7 +557,7 @@ METHOD(Racer, vr_spawn, void(Racer thisveh, entity instance))
     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
 }
@@ -625,9 +625,9 @@ METHOD(Racer, vr_setup, void(Racer thisveh, entity instance))
         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
index f44dcc578464e7a2e485c5da437a286bd721bc87..0150ee98f930fe673f2897d0592540c87981ff3e 100644 (file)
@@ -343,11 +343,11 @@ bool raptor_frame(entity this, float dt)
 
        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;
@@ -369,7 +369,7 @@ bool raptor_frame(entity this, float dt)
                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);
@@ -427,7 +427,7 @@ bool raptor_frame(entity this, float dt)
        }
 
 
-       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);
@@ -471,7 +471,7 @@ bool raptor_takeoff(entity this, float dt)
                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);
@@ -481,7 +481,7 @@ bool raptor_takeoff(entity this, float dt)
        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);
@@ -594,7 +594,7 @@ METHOD(Raptor, vr_enter, void(Raptor thisveh, entity instance))
     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;
@@ -701,7 +701,7 @@ METHOD(Raptor, vr_spawn, void(Raptor thisveh, entity instance))
     }
 
     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;
@@ -720,7 +720,7 @@ METHOD(Raptor, vr_spawn, void(Raptor thisveh, entity instance))
     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))
@@ -739,9 +739,9 @@ 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;
index 09d0eb2af9175c6012b0a903677483e2e7c6d0cc..7352e1dbb4ec89674d4fd45c43534adf36e5fe28 100644 (file)
@@ -294,7 +294,7 @@ bool spiderbot_frame(entity this, float dt)
                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;
@@ -309,7 +309,7 @@ bool spiderbot_frame(entity this, float dt)
        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);
@@ -524,7 +524,7 @@ METHOD(Spiderbot, vr_enter, void(Spiderbot thisveh, entity instance))
     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)
@@ -582,7 +582,7 @@ METHOD(Spiderbot, vr_spawn, void(Spiderbot thisveh, entity instance))
     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;
@@ -599,9 +599,9 @@ METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh, entity instance))
         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
 }
 
index a3f2336a9487b275a8a130a031295c462072d77b..cdf5748e678bf62388ffd85c793cd9194f8656d1 100644 (file)
@@ -162,9 +162,9 @@ CLASS(WeaponPickup, Pickup)
     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
index 9488c4c2c6bc0927a3ba8b30eebeb96baf9a2ccc..6b1797c664e9b38fa36f7eee6d6526d2eea4cd5c 100644 (file)
@@ -20,7 +20,7 @@ MACRO_END
     \
     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); }, \
index d6db7745b9fe1cc5e1ebc8f0f0edcfca78382214..556f58194f5ed5298d52f0aad3f4e6ca3f046e2a 100644 (file)
@@ -35,6 +35,8 @@ REGISTER_NET_TEMP(CLIENT_WEPENT)
        .Weapon switchingweapon;
        .Weapon switchweapon;
 
+       .float m_alpha;
+
        // only for Porto
        .bool angles_held_status;
        .vector angles_held;
index f87f00033762b4fbe18f2d5305989941a191828b..268b591264208458dcada567c028fbdf102be052 100644 (file)
@@ -210,11 +210,11 @@ bool CSQCPlayer_IsLocalPlayer(entity this)
 /** 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)
@@ -239,13 +239,13 @@ void CSQCPlayer_SetCamera()
                }
                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));
index 21e7ecadc454fdc7168a1e0c5314892f5d028749..8b6dd4b731512cec3da19fe489dc512a04245108 100644 (file)
@@ -37,10 +37,11 @@ string WeaponArenaString()
        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);
 
index 594b581fe4408d16351225406971870bcda9c2e2..1c7da72919d68934749d76034cef11cd00ae3b97 100644 (file)
@@ -42,7 +42,7 @@ void XonoticMiscSettingsTab_fill(entity me)
                        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:")));
index 429117ad00cf42f7d73aa7e78a22b737dc17f122..2ec8386955f032bfa6d44bd4396414aea1c27f5b 100644 (file)
@@ -11,7 +11,6 @@
 #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>
index 2bbfb7204df508065c4279227c3ebb92ecf248c1..cc27baf120e93fab2379e7a8643c6e16a1c3c7fe 100644 (file)
@@ -11,7 +11,6 @@
 #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>
index 8a19f06c6e19bb68026cc95a8bba27fcfe97eeb7..4e180f731b2acd7d95efb8e74ba75b091f47f4c8 100644 (file)
@@ -99,6 +99,7 @@ float autocvar_g_ban_sync_timeout;
 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;
index 10ececff6362a3964c13d9c4c3ea181e536bc671..ec84e55167618aea25811a9242963c40a5e22c52 100644 (file)
@@ -595,8 +595,6 @@ float bot_fixcount()
 
        //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;
@@ -604,15 +602,14 @@ float bot_fixcount()
                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;
        }
index 88f423e7a6473939f180e5c014a0085f5ea1af14..e8ca9649fde09b89d84f0175d582c653560d6988 100644 (file)
 #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"
 
@@ -705,6 +708,9 @@ void PutPlayerInServer(entity this)
 
        this.speedrunning = false;
 
+       this.counter_cnt = 0;
+       this.fragsfilter_cnt = 0;
+
        target_voicescript_clear(this);
 
        // reset fields the weapons may use
@@ -721,10 +727,10 @@ void PutPlayerInServer(entity this)
        });
 
        {
-               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);
index c6e4b7879d327f4936695ed77f58674ef9fd2c6b..8b925680679f23006e8008d9d24de88ba35d1d7f 100644 (file)
@@ -17,7 +17,7 @@ CLASS(Client, Object)
     /** 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);
index 232795fa6e14e8c24f75bd2f6a0aaaccd9e215ab..65f231374f56a8053f23a2c2cce49f98df729c15 100644 (file)
@@ -6,6 +6,7 @@
 #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>
 
 //***********************
@@ -183,6 +184,37 @@ spawnfunc(target_give)
        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 */
index 342a829a187b12daa84a0b532bc0269aca79c16b..20e4879d9a37596290a2a24258a7d69db623e21a 100644 (file)
@@ -1,3 +1,5 @@
 #pragma once
 
 bool DoesQ3ARemoveThisEntity(entity this);
+
+.int fragsfilter_cnt;
index 4964bf91e71014cea100bed1b76e5c784d8e91c4..eb05e2c85b7e87e24ba7749d8ceee21ed5760286 100644 (file)
@@ -1236,11 +1236,11 @@ void Fire_ApplyDamage(entity e)
        }
        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);
@@ -1248,6 +1248,8 @@ void Fire_ApplyDamage(entity e)
                                Fire_AddDamage(it, o, d, t, DEATH_FIRE.m_id);
                        }
                });
+       }
+                       
 }
 
 void Fire_ApplyEffect(entity e)
index 05bff142184be3208664ab82f807bb27f4ccd34b..522f4f041cc49af4810c0f53fb2070f30c4e75e4 100644 (file)
@@ -1612,7 +1612,9 @@ float InitiateSuddenDeath()
        // - 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
        }
@@ -1635,11 +1637,7 @@ void InitiateOvertime() // ONLY call this if InitiateSuddenDeath returned true
 {
        ++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);
 }
 
@@ -1778,7 +1776,7 @@ float WinningCondition_RanOutOfSpawns()
        {
                Team_SetTeamScore(Team_GetTeamFromIndex(i), 0);
        }
-       
+
        FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
        {
                if (Team_IsValidTeam(it.team))
index 7b1f69384461b5d6f3c95e2e8c8054e24562279c..7c6fcbafef635c9aff2bddca7ab30ec8c23d45de 100644 (file)
@@ -446,6 +446,8 @@ bool Ban_MaybeEnforceBan(entity client)
        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;
diff --git a/qcsrc/server/item_key.qc b/qcsrc/server/item_key.qc
deleted file mode 100644 (file)
index 2bfdc49..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-#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);
-}
diff --git a/qcsrc/server/item_key.qh b/qcsrc/server/item_key.qh
deleted file mode 100644 (file)
index 50be5f8..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#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
index f8a2cd79ee60ff26314ce71f9d45502017e05f30..cf7266b483a9cb837b6a879ee35559128556da3d 100644 (file)
@@ -600,14 +600,12 @@ void readplayerstartcvars()
                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));
        }
index e0e33e4803c87445641359a8c76824cc821a19a8..03b40c5e12864aa7570c19ff0169c0ec107162b2 100644 (file)
@@ -248,7 +248,7 @@ vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck)
        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)
index abc5df1d726a0e730e2c55402690112ad2cd9fc4..239fb69f0ca8e0e4b20b1da78d8e44897b4e6e5b 100644 (file)
@@ -585,8 +585,8 @@ entity TeamBalance_CheckAllowedTeams(entity for_whom)
                        TeamBalance_IsTeamAllowedInternal(balance, i))
                {
                        TeamBalance_BanTeamsExcept(balance, i);
+                       break;
                }
-               break;
        }
        balance.m_team_balance_state = TEAM_BALANCE_TEAMS_CHECKED;
        return balance;
@@ -881,16 +881,16 @@ void TeamBalance_AutoBalanceBots()
                {
                        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));
@@ -949,16 +949,16 @@ int TeamBalance_GetLargestTeamIndex(entity balance, int teams)
                {
                        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;
index 204b5a7633669ffeac43adcf5c6da6013939d703..4ab5a43717c14e472bc30f0e5cdf6ab98d6bbbb7 100644 (file)
@@ -56,29 +56,20 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                        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)
                {
index 491fd052ea30ef866ad703b80667f5d08648c96d..85f27d5c0b748f7fd6ff26849f253ea68891a50d 100644 (file)
@@ -1,11 +1,3 @@
-electro
-{
-       dpreflectcube cubemaps/default/sky
-       {
-               map textures/electro.tga
-               rgbgen lightingDiffuse
-       }
-}
 nexgun
 {
        dpreflectcube cubemaps/default/sky
index 32f08fc948bbdf7852ab7ba17f18fca721cd5522..af69bbb2145677c5b05116f215f9ec6c9f44d787 100644 (file)
@@ -722,6 +722,8 @@ seta cl_forcemyplayercolors 0 "set to the color value (encoding is same as _cl_c
 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 ""
index 7ad3ced27c0a8c4a82354ac67b92bb9f243f1364..ca9b72eeef4cda9edf6bbd7aee8b34ef2b445290 100644 (file)
@@ -10,7 +10,7 @@ set sv_autotaunt 1 "allow autotaunts on the server"
 // 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"
@@ -372,6 +372,7 @@ set sv_itemstime 1 "enable networking of time left until respawn for items such
 
 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)"
 
@@ -482,6 +483,7 @@ sv_gameplayfix_gravityunaffectedbyticrate 1
 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)"