]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into terencehill/menu_optimization
authorterencehill <piuntn@gmail.com>
Sat, 5 Dec 2015 16:51:26 +0000 (17:51 +0100)
committerterencehill <piuntn@gmail.com>
Sat, 5 Dec 2015 16:51:26 +0000 (17:51 +0100)
179 files changed:
qcsrc/Makefile
qcsrc/client/announcer.qc
qcsrc/client/defs.qh
qcsrc/client/hook.qc
qcsrc/client/hud/hud.qh
qcsrc/client/hud/panel/ammo.qc
qcsrc/client/hud/panel/healtharmor.qc
qcsrc/client/hud/panel/infomessages.qc
qcsrc/client/hud/panel/modicons.qc
qcsrc/client/hud/panel/notify.qc
qcsrc/client/hud/panel/powerups.qc
qcsrc/client/hud/panel/pressedkeys.qc
qcsrc/client/hud/panel/radar.qc
qcsrc/client/hud/panel/score.qc
qcsrc/client/hud/panel/timer.qc
qcsrc/client/hud/panel/weapons.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/progs.inc
qcsrc/client/quickmenu.qc
qcsrc/client/scoreboard.qc
qcsrc/client/shownames.qc
qcsrc/client/view.qc
qcsrc/client/weapons/projectile.qc
qcsrc/common/anim.qc [new file with mode: 0644]
qcsrc/common/anim.qh [new file with mode: 0644]
qcsrc/common/constants.qh
qcsrc/common/csqcmodel_settings.qh
qcsrc/common/deathtypes/all.qh
qcsrc/common/debug.qh
qcsrc/common/effects/qc/globalsound.qc
qcsrc/common/effects/qc/globalsound.qh
qcsrc/common/ent_cs.qc
qcsrc/common/ent_cs.qh
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc
qcsrc/common/minigames/cl_minigames.qc
qcsrc/common/minigames/cl_minigames_hud.qc
qcsrc/common/minigames/minigame/bd.qc
qcsrc/common/minigames/minigame/c4.qc
qcsrc/common/minigames/minigame/nmm.qc
qcsrc/common/minigames/minigame/pong.qc
qcsrc/common/minigames/minigame/pp.qc
qcsrc/common/minigames/minigame/ps.qc
qcsrc/common/minigames/minigame/snake.qc
qcsrc/common/minigames/minigame/ttt.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/movetypes/movetypes.qc
qcsrc/common/movetypes/movetypes.qh
qcsrc/common/movetypes/toss.qc
qcsrc/common/movetypes/walk.qc
qcsrc/common/mutators/base.qh
qcsrc/common/mutators/events.qh
qcsrc/common/mutators/mutator/buffs/all.qh
qcsrc/common/mutators/mutator/buffs/buffs.qc
qcsrc/common/mutators/mutator/buffs/module.inc
qcsrc/common/mutators/mutator/bugrigs/bugrigs.qc
qcsrc/common/mutators/mutator/dodging/dodging.qc
qcsrc/common/mutators/mutator/doublejump/doublejump.qc
qcsrc/common/mutators/mutator/multijump/multijump.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/nades/nades.qh
qcsrc/common/mutators/mutator/new_toys/new_toys.qc
qcsrc/common/mutators/mutator/nix/nix.qc
qcsrc/common/mutators/mutator/overkill/hmg.qc
qcsrc/common/mutators/mutator/overkill/module.inc
qcsrc/common/mutators/mutator/overkill/overkill.qc
qcsrc/common/mutators/mutator/overkill/rpc.qc
qcsrc/common/mutators/mutator/pinata/pinata.qc
qcsrc/common/mutators/mutator/spawn_near_teammate/spawn_near_teammate.qc
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/physics.qc
qcsrc/common/physics.qh
qcsrc/common/playerstats.qc
qcsrc/common/sounds/sound.qh
qcsrc/common/stats.qh
qcsrc/common/triggers/func/door.qc
qcsrc/common/triggers/func/ladder.qc
qcsrc/common/triggers/func/plat.qc
qcsrc/common/triggers/func/train.qc
qcsrc/common/triggers/misc/teleport_dest.qc
qcsrc/common/triggers/subs.qh
qcsrc/common/triggers/teleporters.qc
qcsrc/common/triggers/teleporters.qh
qcsrc/common/triggers/trigger/impulse.qc
qcsrc/common/triggers/trigger/jumppads.qc
qcsrc/common/triggers/trigger/keylock.qc
qcsrc/common/triggers/trigger/secret.qh
qcsrc/common/triggers/trigger/swamp.qc
qcsrc/common/triggers/trigger/teleport.qc
qcsrc/common/triggers/triggers.qc
qcsrc/common/triggers/triggers.qh
qcsrc/common/turrets/cl_turrets.qc
qcsrc/common/vehicles/all.qc
qcsrc/common/vehicles/cl_vehicles.qc
qcsrc/common/vehicles/cl_vehicles.qh
qcsrc/common/vehicles/sv_vehicles.qh
qcsrc/common/vehicles/vehicle/raptor.qc
qcsrc/common/weapons/all.qc
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/config.qc
qcsrc/common/weapons/weapon.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/machinegun.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/mortar.qc
qcsrc/common/weapons/weapon/rifle.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/common/weapons/weapon/vortex.qc
qcsrc/dpdefs/csprogsdefs.qh
qcsrc/dpdefs/doc.md [new file with mode: 0644]
qcsrc/lib/_all.inc
qcsrc/lib/arraylist.qh
qcsrc/lib/csqcmodel/cl_player.qc
qcsrc/lib/enumclass.qh [new file with mode: 0644]
qcsrc/lib/i18n.qh
qcsrc/lib/iter.qh
qcsrc/lib/linkedlist.qh
qcsrc/lib/log.qh
qcsrc/lib/net.qh
qcsrc/lib/oo.qh
qcsrc/lib/registry.qh
qcsrc/lib/stats.qh
qcsrc/lib/unsafe.qh [new file with mode: 0644]
qcsrc/lib/vector.qh
qcsrc/lib/warpzone/client.qc
qcsrc/lib/warpzone/server.qc
qcsrc/lib/warpzone/server.qh
qcsrc/menu/command/menu_cmd.qc
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/menu/xonotic/keybinder.qc
qcsrc/menu/xonotic/serverlist.qc
qcsrc/menu/xonotic/weaponslist.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_client.qh
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_player.qc
qcsrc/server/command/cmd.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_subs.qc
qcsrc/server/g_subs.qh
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/gamemode.qh
qcsrc/server/mutators/mutator/gamemode_ca.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qc
qcsrc/server/mutators/mutator/gamemode_cts.qc
qcsrc/server/mutators/mutator/gamemode_domination.qc
qcsrc/server/mutators/mutator/gamemode_freezetag.qc
qcsrc/server/mutators/mutator/gamemode_race.qc
qcsrc/server/mutators/mutator/gamemode_tdm.qc
qcsrc/server/playerdemo.qc
qcsrc/server/progs.inc
qcsrc/server/race.qc
qcsrc/server/race.qh
qcsrc/server/scores.qc
qcsrc/server/sv_main.qc
qcsrc/server/t_items.qc
qcsrc/server/teamplay.qc
qcsrc/server/weapons/accuracy.qc
qcsrc/server/weapons/common.qc
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/spawning.qc
qcsrc/server/weapons/throwing.qc
qcsrc/server/weapons/weaponsystem.qc
qcsrc/server/weapons/weaponsystem.qh

index 452dfc9a6451ad219bfcfd3b84c9a06b924c504f..b5b77e09ba392461593e1237d834119f90a728ba 100644 (file)
@@ -22,6 +22,7 @@ QCCFLAGS ?= \
        -fftepp -flno -futf8 -fno-bail-on-werror -fftepp-predefs \
        -frelaxed-switch -freturn-assignments \
        $(QCCFLAGS_WATERMARK) \
+       -DNDEBUG=1 \
        $(QCCFLAGS_FEATURES) \
        $(QCCFLAGS_EXTRA)
 
index 6fcdbb9d69354114ce2a0f36582b885218600481..109d014374bff33184d39b5a4deafb855ea757e6 100644 (file)
@@ -21,7 +21,7 @@ void Announcer_Countdown()
 {
        SELFPARAM();
        float starttime = STAT(GAMESTARTTIME);
-       float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
+       float roundstarttime = STAT(ROUNDSTARTTIME);
        if(roundstarttime == -1)
        {
                Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
@@ -74,7 +74,7 @@ void Announcer_Countdown()
 void Announcer_Gamestart()
 {
        float startTime = STAT(GAMESTARTTIME);
-       float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
+       float roundstarttime = STAT(ROUNDSTARTTIME);
        if(roundstarttime > startTime)
                startTime = roundstarttime;
 
@@ -103,7 +103,7 @@ void Announcer_Gamestart()
 // Plays the 1 minute or 5 minutes (of maptime) remaining sound, if client wants it
 void Announcer_Time()
 {
-       float timelimit = getstatf(STAT_TIMELIMIT);
+       float timelimit = STAT(TIMELIMIT);
        float timeleft = max(0, timelimit * 60 + STAT(GAMESTARTTIME) - time);
        float warmup_timeleft = 0;
 
index 98f25cc9037772d9d3a158407109af1fb63e7fe1..069598e3b4613c457f86d0479fdba2a4077edb4c 100644 (file)
@@ -126,7 +126,7 @@ int serverflags;
 
 float uid2name_dialog;
 
-.bool csqcmodel_isdead; // used by shownames and miscfunctions (float getplayerisdead(float) {}) to know when a player is dead
+.bool csqcmodel_isdead; // used by shownames and miscfunctions (entcs_IsDead) to know when a player is dead
 
 #define player_currententnum (spectatee_status > 0 ? spectatee_status : player_localnum + 1)
 
index e8bd4432162f947c541b737d80c732cec61e2f37..818e73782eb84bb35e700c911a3bdac8eb30103a 100644 (file)
@@ -92,7 +92,7 @@ void Draw_GrapplingHook(entity this)
                }
        }
 
-       t = GetPlayerColorForce(self.owner.sv_entnum);
+       t = entcs_GetTeamColor(self.owner.sv_entnum);
 
        switch(self.HookType)
        {
@@ -106,7 +106,7 @@ void Draw_GrapplingHook(entity this)
                                case NUM_TEAM_2: tex = "particles/hook_blue"; rgb = '0.3 0.3 1'; break;
                                case NUM_TEAM_3: tex = "particles/hook_yellow"; rgb = '1 1 0.3'; break;
                                case NUM_TEAM_4: tex = "particles/hook_pink"; rgb = '1 0.3 1'; break;
-                               default: tex = "particles/hook_white"; rgb = getcsqcplayercolor(self.sv_entnum - 1); break;
+                               default: tex = "particles/hook_white"; rgb = entcs_GetColor(self.sv_entnum - 1); break;
                        }
                        break;
                case NET_ENT_CLIENT_ARC_BEAM: // todo
index 764a526b9b950e91c8ca847ad27a0862f4f22828..d30a87273514636a87d1fd9b2ca6903c96e0f67d 100644 (file)
@@ -77,8 +77,8 @@ float complain_weapon_time;
 int ps_primary, ps_secondary;
 int ts_primary, ts_secondary;
 
-int last_switchweapon;
-int last_activeweapon;
+Weapon last_switchweapon;
+Weapon last_activeweapon;
 float weapontime;
 float weaponprevtime;
 
index 236a585985e8c983696284464d02b62277feb090..6c37aa13a89ea740d944d2a46aec0bd1d1c0bb9c 100644 (file)
@@ -113,7 +113,7 @@ void HUD_Ammo()
        }
 
        int rows = 0, columns, row, column;
-       float nade_cnt = getstatf(STAT_NADE_BONUS), nade_score = getstatf(STAT_NADE_BONUS_SCORE);
+       float nade_cnt = STAT(NADE_BONUS), nade_score = STAT(NADE_BONUS_SCORE);
        bool draw_nades = (nade_cnt > 0 || nade_score > 0);
        float nade_statuschange_elapsedtime;
        int total_ammo_count;
@@ -158,6 +158,7 @@ void HUD_Ammo()
                ammo_size.y = newSize;
        }
 
+       Weapon wep = switchweapon;
        int i;
        bool infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
        row = column = 0;
@@ -172,7 +173,7 @@ void HUD_Ammo()
                        DrawAmmoItem(
                                pos,
                                ammo_size,
-                               (get_weaponinfo(switchweapon)).ammo_field,
+                               wep.ammo_field,
                                true,
                                infinite_ammo
                        );
@@ -196,7 +197,7 @@ void HUD_Ammo()
                                pos + eX * column * (ammo_size.x + offset.x) + eY * row * (ammo_size.y + offset.y),
                                ammo_size,
                                ammotype,
-                               ((get_weaponinfo(switchweapon)).ammo_field == ammotype),
+                               (wep.ammo_field == ammotype),
                                infinite_ammo
                        );
 
index 83043293c5c60a60a4a46e3182f8620393cd4ba8..bab17556d477bf9801af055822d450c2fa165a10 100644 (file)
@@ -41,7 +41,7 @@ void HUD_HealthArmor()
                        prev_health = 0;
                        prev_armor = 0;
                }
-               fuel = getstati(STAT_FUEL);
+               fuel = STAT(FUEL);
        }
        else
        {
index 2bcad642609d7b86dfc4b7dd0c1170566057c57a..33f797f3d3201b0a337596a774f709c1c8244ce9 100644 (file)
@@ -62,7 +62,7 @@ void HUD_InfoMessages()
                        if(spectatee_status == -1)
                                s = _("^1Observing");
                        else
-                               s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(current_player));
+                               s = sprintf(_("^1Spectating: ^7%s"), entcs_GetName(current_player));
                        drawInfoMessage(s);
 
                        if(spectatee_status == -1)
index a8cb7c2660042a16077b2069eed0b89f64436e79..8e3166b6ad8f23ef803bc0a779fdaf83c6cd0798 100644 (file)
@@ -10,23 +10,23 @@ void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int
        switch(i)
        {
                case 0:
-                       stat = getstati(STAT_REDALIVE);
+                       stat = STAT(REDALIVE);
                        pic = "player_red.tga";
                        color = '1 0 0';
                        break;
                case 1:
-                       stat = getstati(STAT_BLUEALIVE);
+                       stat = STAT(BLUEALIVE);
                        pic = "player_blue.tga";
                        color = '0 0 1';
                        break;
                case 2:
-                       stat = getstati(STAT_YELLOWALIVE);
+                       stat = STAT(YELLOWALIVE);
                        pic = "player_yellow.tga";
                        color = '1 1 0';
                        break;
                default:
                case 3:
-                       stat = getstati(STAT_PINKALIVE);
+                       stat = STAT(PINKALIVE);
                        pic = "player_pink.tga";
                        color = '1 0 1';
                        break;
@@ -110,7 +110,7 @@ void HUD_Mod_CTF(vector pos, vector mySize)
        int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
        float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime, yellowflag_statuschange_elapsedtime, pinkflag_statuschange_elapsedtime, neutralflag_statuschange_elapsedtime; // time since the status changed
        bool ctf_oneflag; // one-flag CTF mode enabled/disabled
-       int stat_items = getstati(STAT_CTF_FLAGSTATUS, 0, 24);
+       int stat_items = STAT(CTF_FLAGSTATUS);
        float fs, fs2, fs3, size1, size2;
        vector e1, e2;
 
@@ -452,7 +452,7 @@ void HUD_Mod_NexBall(vector pos, vector mySize)
        int stat_items;
 
        stat_items = getstati(STAT_ITEMS, 0, 24);
-       nb_pb_starttime = getstatf(STAT_NB_METERSTART);
+       nb_pb_starttime = STAT(NB_METERSTART);
 
        if (stat_items & IT_KEY1)
                mod_active = 1;
@@ -489,7 +489,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
        mod_active = 1; // race should never hide the mod icons panel
        entity me;
        me = playerslots[player_localnum];
-       float t, score;
+       float score;
        float f; // yet another function has this
        score = me.(scores[ps_primary]);
 
@@ -502,7 +502,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
                rr = CTS_RECORD;
        else
                rr = RACE_RECORD;
-       t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
+       float t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
 
        if(score && (score < t || !t)) {
                db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score));
@@ -598,7 +598,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
                drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
                drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
        } else if(race_status == 2) {
-               if(race_status_name == GetPlayerName(player_localnum) || !race_myrank || race_myrank < rank)
+               if(race_status_name == entcs_GetName(player_localnum) || !race_myrank || race_myrank < rank)
                        drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankgreen", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
                else
                        drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankyellow", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
@@ -630,28 +630,28 @@ void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, in
        switch(i)
        {
                case 0:
-                       stat = getstatf(STAT_DOM_PPS_RED);
+                       stat = STAT(DOM_PPS_RED);
                        pic = "dom_icon_red";
                        color = '1 0 0';
                        break;
                case 1:
-                       stat = getstatf(STAT_DOM_PPS_BLUE);
+                       stat = STAT(DOM_PPS_BLUE);
                        pic = "dom_icon_blue";
                        color = '0 0 1';
                        break;
                case 2:
-                       stat = getstatf(STAT_DOM_PPS_YELLOW);
+                       stat = STAT(DOM_PPS_YELLOW);
                        pic = "dom_icon_yellow";
                        color = '1 1 0';
                        break;
                default:
                case 3:
-                       stat = getstatf(STAT_DOM_PPS_PINK);
+                       stat = STAT(DOM_PPS_PINK);
                        pic = "dom_icon_pink";
                        color = '1 0 1';
                        break;
        }
-       float pps_ratio = stat / getstatf(STAT_DOM_TOTAL_PPS);
+       float pps_ratio = stat / STAT(DOM_TOTAL_PPS);
 
        if(mySize.x/mySize.y > aspect_ratio)
        {
index 821c993fafe30d1abcfe2001847e7c1adcb0008f..3c4b9c10514236a10d5be3f633ebe3c48587a5bb 100644 (file)
@@ -106,7 +106,7 @@ void HUD_Notify()
                {
                        attacker = sprintf(_("Player %d"), count + 1);
                        victim = sprintf(_("Player %d"), count + 2);
-                       icon = get_weaponinfo(min(WEP_FIRST + count * 2, WEP_LAST)).model2;
+                       icon = Weapons_from(min(WEP_FIRST + count * 2, WEP_LAST)).model2;
                        alpha = bound(0, 1.2 - count / entry_count, 1);
                }
                else
index 10446d643605477a839f61b8f6ab89ec5f78e72a..e75f21f3685a0112dc44b5c9a66d07b083a9d564 100644 (file)
@@ -57,7 +57,7 @@ int getPowerupItemAlign(int align, int column, int row, int columns, int rows, b
 void HUD_Powerups()
 {
        int allItems = getstati(STAT_ITEMS, 0, 24);
-       int allBuffs = getstati(STAT_BUFFS, 0, 24);
+       int allBuffs = STAT(BUFFS);
        int strengthTime, shieldTime, superTime;
 
        // Initialize items
@@ -70,7 +70,7 @@ void HUD_Powerups()
 
                strengthTime = bound(0, STAT(STRENGTH_FINISHED) - time, 99);
                shieldTime = bound(0, STAT(INVINCIBLE_FINISHED) - time, 99);
-               superTime = bound(0, getstatf(STAT_SUPERWEAPONS_FINISHED) - time, 99);
+               superTime = bound(0, STAT(SUPERWEAPONS_FINISHED) - time, 99);
 
                if(allItems & IT_UNLIMITED_SUPERWEAPONS)
                        superTime = 99;
index 94cc3287799e2833aa76598a2a1c8b78cdc18ffc..7d6955009764f5389424ed669955b0b6a1da4b99 100644 (file)
@@ -43,8 +43,7 @@ void HUD_PressedKeys()
 
        vector keysize;
        keysize = eX * mySize.x * (1/3.0) + eY * mySize.y * (1/(3.0 - !autocvar_hud_panel_pressedkeys_attack));
-       float pressedkeys;
-       pressedkeys = getstatf(STAT_PRESSED_KEYS);
+       int pressedkeys = STAT(PRESSED_KEYS);
 
        if(autocvar_hud_panel_pressedkeys_attack)
        {
index 1982686c9df3c54d90564942ed356858d599e239..33f4e1e649f2d69fb1fdaeb965e2237660ba867f 100644 (file)
@@ -274,7 +274,6 @@ void HUD_Radar()
        }
 
        int color2;
-       entity tm;
        float scale2d, normalsize, bigsize;
 
        teamradar_origin2d = pos + 0.5 * mySize;
@@ -334,37 +333,34 @@ void HUD_Radar()
 
        draw_teamradar_background(hud_panel_radar_foreground_alpha);
 
-       for(tm = world; (tm = find(tm, classname, "radarlink")); )
-               draw_teamradar_link(tm.origin, tm.velocity, tm.team);
+       FOREACH_ENTITY_CLASS("radarlink", true, LAMBDA(
+               draw_teamradar_link(it.origin, it.velocity, it.team);
+       ));
 
-       vector coord;
-       vector brightcolor;
-       for(tm = world; (tm = findflags(tm, teamradar_icon, 0xFFFFFF)); )
-       {
+       FOREACH_ENTITY_FLAGS(teamradar_icon, 0xFFFFFF, LAMBDA(
                if ( hud_panel_radar_mouse )
-               if ( tm.health > 0 )
-               if ( tm.team == myteam+1 )
+               if ( it.health > 0 )
+               if ( it.team == myteam+1 )
                {
-                       coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(tm.origin));
+                       vector coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(it.origin));
                        if ( vlen(mousepos-coord) < 8 )
                        {
-                               brightcolor_x = min(1,tm.teamradar_color_x*1.5);
-                               brightcolor_y = min(1,tm.teamradar_color_y*1.5);
-                               brightcolor_z = min(1,tm.teamradar_color_z*1.5);
+                               vector brightcolor;
+                               brightcolor_x = min(1,it.teamradar_color_x*1.5);
+                               brightcolor_y = min(1,it.teamradar_color_y*1.5);
+                               brightcolor_z = min(1,it.teamradar_color_z*1.5);
                                drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
                        }
                }
-               entity icon = RadarIcons_from(tm.teamradar_icon);
-               draw_teamradar_icon(tm.origin, icon, tm, spritelookupcolor(tm, icon.netname, tm.teamradar_color), panel_fg_alpha);
-       }
-       for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
-       {
-               if (!tm.m_entcs_private) continue;
-               if (entcs_is_self(tm)) continue;
-               color2 = GetPlayerColor(tm.sv_entnum);
-               //if(color == NUM_SPECTATOR || color == color2)
-                       draw_teamradar_player(tm.origin, tm.angles, Team_ColorRGB(color2));
-       }
+               entity icon = RadarIcons_from(it.teamradar_icon);
+               draw_teamradar_icon(it.origin, icon, it, spritelookupcolor(it, icon.netname, it.teamradar_color), panel_fg_alpha);
+       ));
+       AL_EACH(_entcs, e, it != NULL, LAMBDA(
+               if (!it.m_entcs_private) continue;
+               if (entcs_is_self(it)) continue;
+               color2 = entcs_GetTeam(it.sv_entnum);
+               draw_teamradar_player(it.origin, it.angles, Team_ColorRGB(color2));
+       ));
        draw_teamradar_player(view_origin, view_angles, '1 1 1');
 
        drawresetcliparea();
index dd3000c4cb6ffe1f51b09761b23e710c9f3394b5..d120c1cd181d75cc400a4cf8f57a201fa3607c11 100644 (file)
@@ -46,7 +46,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
                        {
                                rgb = '1 1 0';
                                drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
-                               s = GetPlayerName(player_localnum);
+                               s = entcs_GetName(player_localnum);
                                score = 7;
                        }
                        else
@@ -114,7 +114,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
                }
                if (team_count)
                        score_color = Team_ColorRGB(pl.team) * 0.8;
-               s = textShortenToWidth(GetPlayerName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
+               s = textShortenToWidth(entcs_GetName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
                drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
                drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores[ps_primary])), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
                pos.y += fontsize.y;
index f709b41ec9ba7909f93ab01357a56e7b7fbfc26e..4de0c1e5f6ce76a51a72707db74acb1ad9ad8cbc 100644 (file)
@@ -23,7 +23,7 @@ void HUD_Timer()
        string timer;
        float timelimit, elapsedTime, timeleft, minutesLeft;
 
-       timelimit = getstatf(STAT_TIMELIMIT);
+       timelimit = STAT(TIMELIMIT);
 
        timeleft = max(0, timelimit * 60 + STAT(GAMESTARTTIME) - time);
        timeleft = ceil(timeleft);
index 818663242adf4098143b4ce33a9eb8ddd362fcfb..8970332cd105def4f719790ddfabd38f217e44ec 100644 (file)
@@ -77,18 +77,10 @@ void HUD_Weapons()
                weaponorder_cmp_str = strcat(" ", weaponorder_byimpulse, " ");
 
                weapon_cnt = 0;
-               for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-               {
-                       setself(get_weaponinfo(i));
-                       if(self.impulse >= 0)
-                       {
-                               weaponorder[weapon_cnt] = self;
-                               ++weapon_cnt;
-                       }
-               }
+               FOREACH(Weapons, it != WEP_Null && it.impulse >= 0, LAMBDA(weaponorder[weapon_cnt++] = it));
                for(i = weapon_cnt; i < Weapons_MAX; ++i)
-                       weaponorder[i] = world;
-               heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, world);
+                       weaponorder[i] = NULL;
+               heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, NULL);
 
                weaponorder_cmp_str = string_null;
        }
@@ -100,7 +92,7 @@ void HUD_Weapons()
        {
                if(!weapons_stat)
                        for(i = WEP_FIRST; i <= WEP_LAST; i += floor((WEP_LAST-WEP_FIRST)/5))
-                               weapons_stat |= WepSet_FromWeapon(i);
+                               weapons_stat |= WepSet_FromWeapon(Weapons_from(i));
 
                #if 0
                /// debug code
@@ -109,7 +101,7 @@ void HUD_Weapons()
                        weapons_stat = '0 0 0';
                        float countw = 1 + floor((floor(time * cvar("wep_add"))) % (Weapons_COUNT - 1));
                        for(i = WEP_FIRST; i <= countw; ++i)
-                               weapons_stat |= WepSet_FromWeapon(i);
+                               weapons_stat |= WepSet_FromWeapon(Weapons_from(i));
                }
                #endif
        }
@@ -126,7 +118,7 @@ void HUD_Weapons()
                // do we own this weapon?
                weapon_count = 0;
                for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
-                       if((weapons_stat & WepSet_FromWeapon(weaponorder[i].weapon)) || (weaponorder[i].weapon == complain_weapon))
+                       if((weapons_stat & WepSet_FromWeapon(Weapons_from(weaponorder[i].weapon))) || (weaponorder[i].weapon == complain_weapon))
                                ++weapon_count;
 
 
@@ -140,11 +132,10 @@ void HUD_Weapons()
                // get the all-weapons layout
                int nHidden = 0;
                WepSet weapons_stat = WepSet_GetFromStat();
-               for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
-                       Weapon w = get_weaponinfo(i);
-                       if (weapons_stat & w.m_wepset) continue;
-                       if (w.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1;
-               }
+               FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                       if (weapons_stat & it.m_wepset) continue;
+                       if (it.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1;
+               ));
                vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, padded_panel_size, aspect);
                columns = table_size.x;
                rows = table_size.y;
@@ -348,14 +339,14 @@ void HUD_Weapons()
                // retrieve information about the current weapon to be drawn
                setself(weaponorder[i]);
                weapon_id = self.impulse;
-               isCurrent = (self.weapon == switchweapon);
+               isCurrent = (self.weapon == switchweapon.m_id);
 
                // skip if this weapon doesn't exist
                if(!self || weapon_id < 0) { continue; }
 
                // skip this weapon if we don't own it (and onlyowned is enabled)-- or if weapons_complainbubble is showing for this weapon
                if(autocvar_hud_panel_weapons_onlyowned)
-               if (!((weapons_stat & WepSet_FromWeapon(self.weapon)) || (self.weapon == complain_weapon)))
+               if (!((weapons_stat & WepSet_FromWeapon(Weapons_from(self.weapon))) || (self.weapon == complain_weapon)))
                        continue;
 
                // figure out the drawing position of weapon
@@ -379,7 +370,7 @@ void HUD_Weapons()
                }
 
                // drawing all the weapon items
-               if(weapons_stat & WepSet_FromWeapon(self.weapon))
+               if(weapons_stat & WepSet_FromWeapon(Weapons_from(self.weapon)))
                {
                        // draw the weapon image
                        if(isCurrent)
index f4852ab7f73c9833f181862bd3e4a1e4f2fce63e..f2df818aa62e2123ce86509934beac37b578788b 100644 (file)
@@ -244,7 +244,7 @@ void Playerchecker_Think()
        for(i = 0; i < maxclients; ++i)
        {
                e = playerslots[i];
-               if(GetPlayerName(i) == "")
+               if(entcs_GetName(i) == "")
                {
                        if(e.sort_prev)
                        {
@@ -270,7 +270,7 @@ void Playerchecker_Think()
                                e.ping_packetloss = 0;
                                e.ping_movementloss = 0;
                                //e.gotscores = 0; // we might already have the scores...
-                               SetTeam(e, GetPlayerColor(i)); // will not hurt; later updates come with HUD_UpdatePlayerTeams
+                               SetTeam(e, entcs_GetTeam(i)); // will not hurt; later updates come with HUD_UpdatePlayerTeams
                                RegisterPlayer(e);
                                HUD_UpdatePlayerPos(e);
                        }
@@ -672,7 +672,7 @@ NET_HANDLE(ENT_CLIENT_SPAWNEVENT, bool is_new)
 
                if(is_new)
                {
-                       float teamnum = GetPlayerColor(entnum - 1);
+                       float teamnum = entcs_GetTeam(entnum - 1);
 
                        if(autocvar_cl_spawn_event_particles)
                        {
@@ -727,7 +727,7 @@ void CSQC_Ent_Update(bool isnew)
        else
        {
                serverprevtime = time;
-               serverdeltatime = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+               serverdeltatime = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
                time = serverprevtime + serverdeltatime;
        }
 
@@ -1074,7 +1074,7 @@ NET_HANDLE(TE_CSQC_RACE, bool isNew)
                                strunzone(grecordholder[pos-1]);
                        grecordholder[pos-1] = strzone(ReadString());
                        grecordtime[pos-1] = ReadInt24_t();
-                       if(grecordholder[pos-1] == GetPlayerName(player_localnum))
+                       if(grecordholder[pos-1] == entcs_GetName(player_localnum))
                                race_myrank = pos;
                        break;
                case RACE_NET_SERVER_STATUS:
index a6aebc61c64cfa608f4367e68d11137962734c70..91d5de09bd1b36de04e1b32c4735bd52e18b480c 100644 (file)
@@ -2,6 +2,7 @@
 #define CLIENT_MAIN_H
 
 #include "../common/constants.qh"
+#include "../common/weapons/all.qh"
 
 // --------------------------------------------------------------------------
 // MENU Functionality
@@ -94,9 +95,9 @@ bool button_zoom;
 bool spectatorbutton_zoom;
 bool button_attack2;
 
-int activeweapon;
-int switchingweapon;
-#define switchweapon STAT(SWITCHWEAPON)
+Weapon activeweapon;
+Weapon switchingweapon;
+Weapon switchweapon;
 float current_viewzoom;
 float zoomin_effect;
 float warmup_stage;
index 4a6b587882c744ae15e9c16036025acbbca336d6..775e031481ff9141b79411b3d586273de6f07dc1 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "weapons/projectile.qc" // TODO
 
+#include "../common/anim.qc"
 #include "../common/animdecide.qc"
 #include "../common/effects/effectinfo.qc"
 #include "../common/ent_cs.qc"
@@ -62,6 +63,7 @@
 #include "../lib/warpzone/anglestransform.qc"
 #include "../lib/warpzone/client.qc"
 #include "../lib/warpzone/common.qc"
+#include "../lib/warpzone/server.qc"
 #include "../lib/warpzone/util_server.qc"
 
 #if BUILD_MOD
index a4fdfea382f170bfb1f69bb3583a7883901c7c56..90f6c171c88c621a3b7b72ad3631f62bec7c87e7 100644 (file)
@@ -758,7 +758,7 @@ void HUD_Quickmenu_PlayerListEntries(string cmd, float teamplayers, float withou
                        continue;
                if(without_me && pl.sv_entnum == player_localnum)
                        continue;
-               QUICKMENU_ENTRY(GetPlayerName(pl.sv_entnum), sprintf(cmd, GetPlayerName(pl.sv_entnum)))
+               QUICKMENU_ENTRY(entcs_GetName(pl.sv_entnum), sprintf(cmd, entcs_GetName(pl.sv_entnum)))
        }
 
        return;
@@ -847,7 +847,7 @@ void QuickMenu_Default(string target_submenu)
        QUICKMENU_SMENU(CTX(_("QMCMD^Call a vote")), "Call a vote")
                QUICKMENU_ENTRY(CTX(_("QMCMD^Restart the map")), "vcall restart")
                QUICKMENU_ENTRY(CTX(_("QMCMD^End match")), "vcall endmatch")
-               if(getstatf(STAT_TIMELIMIT) > 0)
+               if(STAT(TIMELIMIT) > 0)
                {
                QUICKMENU_ENTRY(CTX(_("QMCMD^Reduce match time")), "vcall reducematchtime")
                QUICKMENU_ENTRY(CTX(_("QMCMD^Extend match time")), "vcall extendmatchtime")
index a42f14f03505cb1892be8913fdd2303c72a4454c..4d9a8c69d0c35c91fe9496da174b91d33ea29e9c 100644 (file)
@@ -109,7 +109,7 @@ void HUD_UpdatePlayerTeams()
        for(pl = players.sort_next; pl; pl = pl.sort_next)
        {
                num += 1;
-               Team = GetPlayerColor(pl.sv_entnum);
+               Team = entcs_GetTeam(pl.sv_entnum);
                if(SetTeam(pl, Team))
                {
                        tmp = pl.sort_prev;
@@ -146,8 +146,8 @@ int HUD_CompareScore(float vl, float vr, int f)
 float HUD_ComparePlayerScores(entity left, entity right)
 {
        float vl, vr, r;
-       vl = GetPlayerColor(left.sv_entnum);
-       vr = GetPlayerColor(right.sv_entnum);
+       vl = entcs_GetTeam(left.sv_entnum);
+       vr = entcs_GetTeam(right.sv_entnum);
 
        if(!left.gotscores)
                vl = NUM_SPECTATOR;
@@ -571,7 +571,7 @@ string HUD_GetField(entity pl, int field)
                                        hud_field_icon2_rgb = colormapPaletteColor(f % 16, 1);
                                }
                        }
-                       return GetPlayerName(pl.sv_entnum);
+                       return entcs_GetName(pl.sv_entnum);
 
                case SP_FRAGS:
                        f = pl.(scores[SP_KILLS]);
@@ -710,7 +710,7 @@ void HUD_PrintScoreboardItem(vector pos, vector item_size, entity pl, float is_s
        string str;
        int field;
        float is_spec;
-       is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
+       is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
 
        if((rgb == '1 1 1') && (!is_spec)) {
                rgb.x = autocvar_scoreboard_color_bg_r + 0.5;
@@ -1001,17 +1001,15 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
        WepSet weapons_inmap = WepSet_GetFromStat_InMap();
        float initial_posx = pos.x;
        int disownedcnt = 0;
-       for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
-               Weapon e = get_weaponinfo(i);
-               setself(e);
-               if (!self.weapon) continue;
+       FOREACH(Weapons, it != WEP_Null, LAMBDA(
+               if (!it.weapon) continue;
 
                int weapon_stats = weapon_accuracy[i - WEP_FIRST];
 
-               WepSet set = e.m_wepset;
+               WepSet set = it.m_wepset;
                if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
                        ++disownedcnt;
-       }
+       ));
 
        int weapon_cnt = (Weapons_COUNT - 1) - disownedcnt;
        if (weapon_cnt <= 0) return pos;
@@ -1065,13 +1063,11 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
        vector tmpos = pos;
 
        int column = 0;
-       for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
-               Weapon e = get_weaponinfo(i);
-               setself(e);
-               if (!self.weapon) continue;
+       FOREACH(Weapons, it != WEP_Null, LAMBDA(
+               if (!it.weapon) continue;
                int weapon_stats = weapon_accuracy[i - WEP_FIRST];
 
-               WepSet set = e.m_wepset;
+               WepSet set = it.m_wepset;
                if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
                        continue;
 
@@ -1082,7 +1078,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
                        weapon_alpha = 0.2 * scoreboard_alpha_fg;
 
                // weapon icon
-               drawpic_aspect_skin(tmpos, self.model2, '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+               drawpic_aspect_skin(tmpos, it.model2, '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
                // the accuracy
                if (weapon_stats >= 0) {
                        weapons_with_stats += 1;
@@ -1107,7 +1103,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
                        pos.y += height;
                }
                ++column;
-       }
+       ));
 
        if (weapons_with_stats)
                average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
@@ -1137,12 +1133,12 @@ vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
        string val;
 
        // get monster stats
-       stat_monsters_killed = getstatf(STAT_MONSTERS_KILLED);
-       stat_monsters_total = getstatf(STAT_MONSTERS_TOTAL);
+       stat_monsters_killed = STAT(MONSTERS_KILLED);
+       stat_monsters_total = STAT(MONSTERS_TOTAL);
 
        // get secrets stats
-       stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
-       stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
+       stat_secrets_found = STAT(SECRETS_FOUND);
+       stat_secrets_total = STAT(SECRETS_TOTAL);
 
        // get number of rows
        if(stat_secrets_total)
@@ -1201,7 +1197,7 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl,  vector rgb, vector bg_
                return pos;
 
        float is_spec;
-       is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
+       is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
        vector hl_rgb;
        hl_rgb.x = autocvar_scoreboard_color_bg_r + 0.5;
        hl_rgb.y = autocvar_scoreboard_color_bg_g + 0.5;
@@ -1230,7 +1226,7 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl,  vector rgb, vector bg_
                        continue;
                n = grecordholder[i];
                p = count_ordinal(i+1);
-               if(grecordholder[i] == GetPlayerName(player_localnum))
+               if(grecordholder[i] == entcs_GetName(player_localnum))
                        drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize.y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
                else if(!(i % 2) && scoreboard_highlight)
                        drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize.y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
@@ -1406,9 +1402,9 @@ void HUD_DrawScoreboard()
        // Print info string
        float tl, fl, ll;
        str = sprintf(_("playing ^3%s^7 on ^2%s^7"), MapInfo_Type_ToText(gametype), shortmapname);
-       tl = getstatf(STAT_TIMELIMIT);
-       fl = getstatf(STAT_FRAGLIMIT);
-       ll = getstatf(STAT_LEADLIMIT);
+       tl = STAT(TIMELIMIT);
+       fl = STAT(FRAGLIMIT);
+       ll = STAT(LEADLIMIT);
        if(gametype == MAPINFO_TYPE_LMS)
        {
                if(tl > 0)
@@ -1462,7 +1458,7 @@ void HUD_DrawScoreboard()
        drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, true, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
 
        // print information about respawn status
-       float respawn_time = getstatf(STAT_RESPAWN_TIME);
+       float respawn_time = STAT(RESPAWN_TIME);
        if(!intermission)
        if(respawn_time)
        {
index f13efdde050df357b3f98e3f14d74b56e1624bf4..66f313d3a2fad3aba0ed8904d72aff70013b6b8d 100644 (file)
@@ -24,6 +24,7 @@ STATIC_INIT(shownames_ent)
        for (int i = 0; i < maxclients; ++i)
        {
                entity e = new(shownames_tag);
+               make_pure(e);
                e.sv_entnum = i + 1;
                LL_PUSH(shownames_ent, e);
        }
@@ -99,7 +100,7 @@ void Draw_ShowNames(entity this)
        // multiply by player alpha
        if (!this.sameteam || (this.sv_entnum == player_localentnum))
        {
-               float f = getplayeralpha(this.sv_entnum - 1);
+               float f = entcs_GetAlpha(this.sv_entnum - 1);
                if (f == 0) f = 1;
                if (f < 0) f = 0;
                // FIXME: alpha is negative when dead, breaking death fade
@@ -150,9 +151,9 @@ void Draw_ShowNames(entity this)
                                        DRAWFLAG_NORMAL);
                        }
                }
-               string s = GetPlayerName(this.sv_entnum - 1);
+               string s = entcs_GetName(this.sv_entnum - 1);
                if ((autocvar_hud_shownames_decolorize == 1 && teamplay)
-                   || autocvar_hud_shownames_decolorize == 2) s = playername(s, GetPlayerColor(this.sv_entnum - 1));
+                   || autocvar_hud_shownames_decolorize == 2) s = playername(s, entcs_GetTeam(this.sv_entnum - 1));
                drawfontscale = '1 1 0' * resize;
                s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
                float width = stringwidth(s, true, '1 1 0' * autocvar_hud_shownames_fontsize);
@@ -167,7 +168,15 @@ void Draw_ShowNames_All()
        if (!autocvar_hud_shownames) return;
        LL_EACH(shownames_ent, true, LAMBDA(
                entity entcs = entcs_receiver(i);
-               if (!entcs) continue;
+               if (!entcs)
+               {
+                       make_pure(it);
+                       continue;
+               }
+               make_impure(it);
+               assert(entcs.think, eprint(entcs));
+               WITH(entity, self, entcs, entcs.think());
+               if (!entcs.has_origin) continue;
                if (entcs.m_entcs_private)
                {
                        it.healthvalue = entcs.healthvalue;
@@ -180,8 +189,8 @@ void Draw_ShowNames_All()
                        it.armorvalue = 0;
                        it.sameteam = false;
                }
-               bool dead = getplayerisdead(i);
-               if (!it.csqcmodel_isdead && entcs.has_origin) setorigin(it, entcs.origin);
+               bool dead = entcs_IsDead(i) || entcs_IsSpectating(i);
+               if (!it.csqcmodel_isdead) setorigin(it, entcs.origin);
                it.csqcmodel_isdead = dead;
                Draw_ShowNames(it);
        ));
index 0f1a43e2faa21ec3a701a8266a407283f6148396..85fea0d1b77c81406d4f4930beffd48895f05e69 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "mutators/events.qh"
 
+#include "../common/anim.qh"
 #include "../common/constants.qh"
 #include "../common/debug.qh"
 #include "../common/mapinfo.qh"
 #include "../lib/warpzone/client.qh"
 #include "../lib/warpzone/common.qh"
 
+#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;
+
+bool autocvar_cl_bobmodel;
+float autocvar_cl_bobmodel_speed;
+float autocvar_cl_bobmodel_side;
+float autocvar_cl_bobmodel_up;
+
+float autocvar_cl_followmodel;
+float autocvar_cl_followmodel_side_speed;
+float autocvar_cl_followmodel_side_highpass;
+float autocvar_cl_followmodel_side_highpass1;
+float autocvar_cl_followmodel_side_limit;
+float autocvar_cl_followmodel_side_lowpass;
+float autocvar_cl_followmodel_up_speed;
+float autocvar_cl_followmodel_up_highpass;
+float autocvar_cl_followmodel_up_highpass1;
+float autocvar_cl_followmodel_up_limit;
+float autocvar_cl_followmodel_up_lowpass;
+
+float autocvar_cl_leanmodel;
+float autocvar_cl_leanmodel_side_speed;
+float autocvar_cl_leanmodel_side_highpass;
+float autocvar_cl_leanmodel_side_highpass1;
+float autocvar_cl_leanmodel_side_lowpass;
+float autocvar_cl_leanmodel_side_limit;
+float autocvar_cl_leanmodel_up_speed;
+float autocvar_cl_leanmodel_up_highpass;
+float autocvar_cl_leanmodel_up_highpass1;
+float autocvar_cl_leanmodel_up_lowpass;
+float autocvar_cl_leanmodel_up_limit;
+
+#define lowpass(value, frac, ref_store, ret) do \
+{ \
+       float __frac = bound(0, frac, 1); \
+       ret = ref_store = ref_store * (1 - __frac) + (value) * __frac; \
+} while (0)
+
+#define lowpass_limited(value, frac, limit, ref_store, ret) do \
+{ \
+       float __ignore; lowpass(value, frac, ref_store, __ignore); \
+       ret = ref_store = bound((value) - (limit), ref_store, (value) + (limit)); \
+} while (0)
+
+#define highpass(value, frac, ref_store, ret) do \
+{ \
+       float __f; lowpass(value, frac, ref_store, __f); \
+       ret = (value) - __f; \
+} while (0)
+
+#define highpass_limited(value, frac, limit, ref_store, ret) do \
+{ \
+       float __f; lowpass_limited(value, frac, limit, ref_store, __f); \
+       ret = (value) - __f; \
+} while (0)
+
+#define lowpass3(value, fracx, fracy, fracz, ref_store, ref_out) do \
+{ \
+       lowpass(value.x, fracx, ref_store.x, ref_out.x); \
+       lowpass(value.y, fracy, ref_store.y, ref_out.y); \
+       lowpass(value.z, fracz, ref_store.z, ref_out.z); \
+} while (0)
+
+#define highpass3(value, fracx, fracy, fracz, ref_store, ref_out) do \
+{ \
+       highpass(value.x, fracx, ref_store.x, ref_out.x); \
+       highpass(value.y, fracy, ref_store.y, ref_out.y); \
+       highpass(value.z, fracz, ref_store.z, ref_out.z); \
+} while (0)
+
+#define highpass3_limited(value, fracx, limitx, fracy, limity, fracz, limitz, ref_store, ref_out) do \
+{ \
+       highpass_limited(value.x, fracx, limitx, ref_store.x, ref_out.x); \
+       highpass_limited(value.y, fracy, limity, ref_store.y, ref_out.y); \
+       highpass_limited(value.z, fracz, limitz, ref_store.z, ref_out.z); \
+} while (0)
+
+void viewmodel_animate(entity this)
+{
+       static float prevtime;
+       float frametime = (time - prevtime) * STAT(MOVEVARS_TIMESCALE);
+       prevtime = time;
+
+       if (autocvar_chase_active) return;
+       if (getstati(STAT_HEALTH) <= 0) return;
+
+       entity view = CSQCModel_server2csqc(player_localentnum - 1);
+
+       bool clonground = !(view.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
+       static bool oldonground;
+       static float hitgroundtime;
+       static float lastongroundtime;
+       if (clonground)
+       {
+               float f = time; // cl.movecmd[0].time
+               if (!oldonground)
+                       hitgroundtime = f;
+               lastongroundtime = f;
+       }
+       oldonground = clonground;
+
+       vector gunorg = '0 0 0', gunangles = '0 0 0';
+       static vector gunorg_prev = '0 0 0', gunangles_prev = '0 0 0';
+
+       bool teleported = view.csqcmodel_teleported;
+
+       // 1. if we teleported, clear the frametime... the lowpass will recover the previous value then
+       if (teleported)
+       {
+               // try to fix the first highpass; result is NOT
+               // perfect! TODO find a better fix
+               gunangles_prev = view_angles;
+               gunorg_prev = view_origin;
+       }
+
+       static vector gunorg_highpass = '0 0 0';
+
+       // 2. for the gun origin, only keep the high frequency (non-DC) parts, which is "somewhat like velocity"
+       gunorg_highpass += gunorg_prev;
+       highpass3_limited(view_origin,
+               frametime * autocvar_cl_followmodel_side_highpass1, autocvar_cl_followmodel_side_limit,
+               frametime * autocvar_cl_followmodel_side_highpass1, autocvar_cl_followmodel_side_limit,
+               frametime * autocvar_cl_followmodel_up_highpass1, autocvar_cl_followmodel_up_limit,
+               gunorg_highpass, gunorg);
+       gunorg_prev = view_origin;
+       gunorg_highpass -= gunorg_prev;
+
+       static vector gunangles_highpass = '0 0 0';
+
+       // in the highpass, we _store_ the DIFFERENCE to the actual view angles...
+       gunangles_highpass += gunangles_prev;
+       PITCH(gunangles_highpass) += 360 * floor((PITCH(view_angles) - PITCH(gunangles_highpass)) / 360 + 0.5);
+       YAW(gunangles_highpass) += 360 * floor((YAW(view_angles) - YAW(gunangles_highpass)) / 360 + 0.5);
+       ROLL(gunangles_highpass) += 360 * floor((ROLL(view_angles) - ROLL(gunangles_highpass)) / 360 + 0.5);
+       highpass3_limited(view_angles,
+               frametime * autocvar_cl_leanmodel_up_highpass1, autocvar_cl_leanmodel_up_limit,
+               frametime * autocvar_cl_leanmodel_side_highpass1, autocvar_cl_leanmodel_side_limit,
+               0, 0,
+               gunangles_highpass, gunangles);
+       gunangles_prev = view_angles;
+       gunangles_highpass -= gunangles_prev;
+
+       // 3. calculate the RAW adjustment vectors
+       gunorg.x *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_side_speed : 0);
+       gunorg.y *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_side_speed : 0);
+       gunorg.z *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_up_speed : 0);
+
+       PITCH(gunangles) *= (autocvar_cl_leanmodel ? -autocvar_cl_leanmodel_up_speed : 0);
+       YAW(gunangles) *= (autocvar_cl_leanmodel ? -autocvar_cl_leanmodel_side_speed : 0);
+       ROLL(gunangles) = 0;
+
+       static vector gunorg_adjustment_highpass;
+       static vector gunorg_adjustment_lowpass;
+       static vector gunangles_adjustment_highpass;
+       static vector gunangles_adjustment_lowpass;
+
+       // 4. perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!)
+       //    trick: we must do the lowpass LAST, so the lowpass vector IS the final vector!
+       highpass3(gunorg,
+               frametime * autocvar_cl_followmodel_side_highpass,
+               frametime * autocvar_cl_followmodel_side_highpass,
+               frametime * autocvar_cl_followmodel_up_highpass,
+               gunorg_adjustment_highpass, gunorg);
+       lowpass3(gunorg,
+               frametime * autocvar_cl_followmodel_side_lowpass,
+               frametime * autocvar_cl_followmodel_side_lowpass,
+               frametime * autocvar_cl_followmodel_up_lowpass,
+               gunorg_adjustment_lowpass, gunorg);
+       // we assume here: PITCH = 0, YAW = 1, ROLL = 2
+       highpass3(gunangles,
+               frametime * autocvar_cl_leanmodel_up_highpass,
+               frametime * autocvar_cl_leanmodel_side_highpass,
+               0,
+               gunangles_adjustment_highpass, gunangles);
+       lowpass3(gunangles,
+               frametime * autocvar_cl_leanmodel_up_lowpass,
+               frametime * autocvar_cl_leanmodel_side_lowpass,
+               0,
+               gunangles_adjustment_lowpass, gunangles);
+       float xyspeed = bound(0, vlen(vec2(view.velocity)), 400);
+
+       // vertical view bobbing code
+       // TODO: cl_bob
+
+       // horizontal view bobbing code
+       // TODO: cl_bob2
+
+       // fall bobbing code
+       // causes the view to swing down and back up when touching the ground
+       // TODO: cl_bobfall
+
+       // gun model bobbing code
+       if (autocvar_cl_bobmodel)
+       {
+               // calculate for swinging gun model
+               // the gun bobs when running on the ground, but doesn't bob when you're in the air.
+               // Sajt: I tried to smooth out the transitions between bob and no bob, which works
+               // for the most part, but for some reason when you go through a message trigger or
+               // pick up an item or anything like that it will momentarily jolt the gun.
+               vector forward, right, up;
+               float bspeed;
+               float t = 1;
+               float s = time * autocvar_cl_bobmodel_speed;
+               if (clonground)
+               {
+                       if (time - hitgroundtime < 0.2)
+                       {
+                               // just hit the ground, speed the bob back up over the next 0.2 seconds
+                               t = time - hitgroundtime;
+                               t = bound(0, t, 0.2);
+                               t *= 5;
+                       }
+               }
+               else
+               {
+                       // recently left the ground, slow the bob down over the next 0.2 seconds
+                       t = time - lastongroundtime;
+                       t = 0.2 - bound(0, t, 0.2);
+                       t *= 5;
+               }
+               bspeed = xyspeed * 0.01;
+               MAKEVECTORS(makevectors, view_angles, forward, right, up);
+               float bobr = bspeed * autocvar_cl_bobmodel_side * autocvar_cl_viewmodel_scale * sin(s) * t;
+               gunorg += bobr * right;
+               float bobu = bspeed * autocvar_cl_bobmodel_up * autocvar_cl_viewmodel_scale * cos(s * 2) * t;
+               gunorg += bobu * up;
+       }
+       vector v = rotate(gunorg, YAW(view_angles) * DEG2RAD); // rotate world coordinates to relative ones
+       v.z = gunorg.z;
+       this.origin += v;
+       gunangles.x = -gunangles.x; // pitch was inverted, now that actually matters
+       this.angles += gunangles;
+}
+
+.vector viewmodel_origin, viewmodel_angles;
+.float weapon_nextthink;
+.float weapon_eta_last;
+.float weapon_switchdelay;
+
+void viewmodel_draw(entity this)
+{
+       int mask = (intermission || (getstati(STAT_HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
+       float a = this.alpha;
+       int c = stof(getplayerkeyvalue(current_player, "colors"));
+       vector g;
+       Weapon wep = activeweapon;
+       if (!(g = wep.wr_glow(wep))) g = colormapPaletteColor(c & 0x0F, true) * 2;
+       entity me = CSQCModel_server2csqc(player_localentnum - 1);
+       int fx = ((me.csqcmodel_effects & EFMASK_CHEAP)
+               | EF_NODEPTHTEST)
+               &~ (EF_FULLBRIGHT); // can mask team color, so get rid of it
+       for (entity e = this; e; e = e.weaponchild)
+       {
+               e.drawmask = mask;
+               e.alpha = a;
+               e.colormap = 256 + c;  // colormap == 0 is black, c == 0 is white
+               e.glowmod = g;
+               e.csqcmodel_effects = fx;
+               WITH(entity, self, e, CSQCModel_Effects_Apply());
+       }
+       {
+               static string name_last;
+               string name = wep.mdl;
+               if (name != name_last)
+               {
+                       name_last = name;
+                       CL_WeaponEntity_SetModel(this, name);
+                       this.viewmodel_origin = this.origin;
+                       this.viewmodel_angles = this.angles;
+               }
+               anim_update(this);
+               if (!this.animstate_override)
+                       anim_set(this, this.anim_idle, true, false, false);
+       }
+       float f = 0; // 0..1; 0: fully active
+       float eta = (this.weapon_nextthink - time) / STAT(WEAPONRATEFACTOR);
+       if (eta <= 0) f = this.weapon_eta_last;
+       else switch (this.state)
+       {
+               case WS_RAISE:
+               {
+                       f = eta / max(eta, this.weapon_switchdelay);
+                       break;
+               }
+               case WS_DROP:
+               {
+                       f = 1 - eta / max(eta, this.weapon_switchdelay);
+                       break;
+               }
+               case WS_CLEAR:
+               {
+                       f = 1;
+                       break;
+               }
+       }
+       this.weapon_eta_last = f;
+       this.origin = this.viewmodel_origin;
+       this.angles = this.viewmodel_angles;
+       this.angles_x = (-90 * f * f);
+       viewmodel_animate(this);
+       setorigin(this, this.origin);
+}
+
+entity viewmodel;
+STATIC_INIT(viewmodel) {
+    viewmodel = new(viewmodel);
+    make_pure(viewmodel);
+       viewmodel.draw = viewmodel_draw;
+}
+
 entity porto;
 vector polyline[16];
 void Porto_Draw(entity this)
@@ -36,7 +348,7 @@ void Porto_Draw(entity this)
        vector p, dir, ang, q, nextdir;
        float portal_number, portal1_idx;
 
-       if(activeweapon != WEP_PORTO.m_id || spectatee_status || gametype == MAPINFO_TYPE_NEXBALL)
+       if(activeweapon != WEP_PORTO || spectatee_status || gametype == MAPINFO_TYPE_NEXBALL)
                return;
        if(g_balance_porto_secondary)
                return;
@@ -136,7 +448,7 @@ vector GetCurrentFov(float fov)
        zoomdir = button_zoom;
        if(hud == HUD_NORMAL)
        if(switchweapon == activeweapon)
-       if((activeweapon == WEP_VORTEX.m_id && vortex_scope) || (activeweapon == WEP_RIFLE.m_id && rifle_scope)) // do NOT use switchweapon here
+       if((activeweapon == WEP_VORTEX && vortex_scope) || (activeweapon == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here
                zoomdir += button_attack2;
        if(spectatee_status > 0 || isdemo())
        {
@@ -299,7 +611,7 @@ float EnemyHitCheck()
                return SHOTTYPE_HITWORLD;
        if(n > maxclients)
                return SHOTTYPE_HITWORLD;
-       t = GetPlayerColor(n - 1);
+       t = entcs_GetTeam(n - 1);
        if(teamplay)
                if(t == myteam)
                        return SHOTTYPE_HITTEAM;
@@ -323,17 +635,17 @@ float TrueAimCheck()
 
        switch(activeweapon) // WEAPONTODO
        {
-               case WEP_TUBA.m_id: // no aim
-               case WEP_PORTO.m_id: // shoots from eye
-               case WEP_NEXBALL.m_id: // shoots from eye
-               case WEP_HOOK.m_id: // no trueaim
-               case WEP_MORTAR.m_id: // toss curve
+               case WEP_TUBA: // no aim
+               case WEP_PORTO: // shoots from eye
+               case WEP_NEXBALL: // shoots from eye
+               case WEP_HOOK: // no trueaim
+               case WEP_MORTAR: // toss curve
                        return SHOTTYPE_HITWORLD;
-               case WEP_VORTEX.m_id:
-               case WEP_VAPORIZER.m_id:
+               case WEP_VORTEX:
+               case WEP_VAPORIZER:
                        mv = MOVE_NORMAL;
                        break;
-               case WEP_RIFLE.m_id:
+               case WEP_RIFLE:
                        ta = trueaim_rifle;
                        mv = MOVE_NORMAL;
                        if(zoomscript_caught)
@@ -342,19 +654,19 @@ float TrueAimCheck()
                                return EnemyHitCheck();
                        }
                        break;
-               case WEP_DEVASTATOR.m_id: // projectile has a size!
+               case WEP_DEVASTATOR: // projectile has a size!
                        mi = '-3 -3 -3';
                        ma = '3 3 3';
                        break;
-               case WEP_FIREBALL.m_id: // projectile has a size!
+               case WEP_FIREBALL: // projectile has a size!
                        mi = '-16 -16 -16';
                        ma = '16 16 16';
                        break;
-               case WEP_SEEKER.m_id: // projectile has a size!
+               case WEP_SEEKER: // projectile has a size!
                        mi = '-2 -2 -2';
                        ma = '2 2 2';
                        break;
-               case WEP_ELECTRO.m_id: // projectile has a size!
+               case WEP_ELECTRO: // projectile has a size!
                        mi = '0 0 -3';
                        ma = '0 0 -3';
                        break;
@@ -362,7 +674,7 @@ float TrueAimCheck()
 
        vector traceorigin = entcs_receiver(player_localentnum - 1).origin + (eZ * getstati(STAT_VIEWHEIGHT));
 
-       vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
+       vecs = decompressShotOrigin(STAT(SHOTORG));
 
        traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
        trueaimpoint = trace_endpos;
@@ -475,12 +787,12 @@ void UpdateDamage()
 {
        // accumulate damage with each stat update
        static float damage_total_prev = 0;
-       float damage_total = getstati(STAT_DAMAGE_DEALT_TOTAL);
+       float damage_total = STAT(DAMAGE_DEALT_TOTAL);
        float unaccounted_damage_new = COMPARE_INCREASING(damage_total, damage_total_prev);
        damage_total_prev = damage_total;
 
        static float damage_dealt_time_prev = 0;
-       float damage_dealt_time = getstatf(STAT_HIT_TIME);
+       float damage_dealt_time = STAT(HIT_TIME);
        if (damage_dealt_time != damage_dealt_time_prev)
        {
                unaccounted_damage += unaccounted_damage_new;
@@ -501,7 +813,7 @@ void HitSound()
 
        static float hitsound_time_prev = 0;
        // HACK: the only way to get the arc to sound consistent with pitch shift is to ignore cl_hitsound_antispam_time
-       float arc_hack = activeweapon == WEP_ARC.m_id && autocvar_cl_hitsound >= 2;
+       float arc_hack = activeweapon == WEP_ARC && autocvar_cl_hitsound >= 2;
        if (arc_hack || COMPARE_INCREASING(time, hitsound_time_prev) > autocvar_cl_hitsound_antispam_time)
        {
                if (autocvar_cl_hitsound && unaccounted_damage)
@@ -536,7 +848,7 @@ void HitSound()
        }
 
        static float typehit_time_prev = 0;
-       float typehit_time = getstatf(STAT_TYPEHIT_TIME);
+       float typehit_time = STAT(TYPEHIT_TIME);
        if (COMPARE_INCREASING(typehit_time, typehit_time_prev) > autocvar_cl_hitsound_antispam_time)
        {
                sound(world, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE);
@@ -607,7 +919,7 @@ void HUD_Crosshair()
 
                if(autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1))
                {
-                       e = get_weaponinfo(switchingweapon);
+                       e = switchingweapon;
                        if(e)
                        {
                                if(autocvar_crosshair_per_weapon)
@@ -712,7 +1024,7 @@ void HUD_Crosshair()
 
                if(autocvar_crosshair_pickup)
                {
-                       float stat_pickup_time = getstatf(STAT_LAST_PICKUP);
+                       float stat_pickup_time = STAT(LAST_PICKUP);
 
                        if(pickup_crosshair_time < stat_pickup_time)
                        {
@@ -819,16 +1131,16 @@ void HUD_Crosshair()
                                ring_scale = autocvar_crosshair_ring_size;
 
                                float weapon_clipload, weapon_clipsize;
-                               weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD);
-                               weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE);
+                               weapon_clipload = STAT(WEAPON_CLIPLOAD);
+                               weapon_clipsize = STAT(WEAPON_CLIPSIZE);
 
                                float ok_ammo_charge, ok_ammo_chargepool;
-                               ok_ammo_charge = getstatf(STAT_OK_AMMO_CHARGE);
-                               ok_ammo_chargepool = getstatf(STAT_OK_AMMO_CHARGEPOOL);
+                               ok_ammo_charge = STAT(OK_AMMO_CHARGE);
+                               ok_ammo_chargepool = STAT(OK_AMMO_CHARGEPOOL);
 
                                float vortex_charge, vortex_chargepool;
-                               vortex_charge = getstatf(STAT_VORTEX_CHARGE);
-                               vortex_chargepool = getstatf(STAT_VORTEX_CHARGEPOOL);
+                               vortex_charge = STAT(VORTEX_CHARGE);
+                               vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
 
                                float arc_heat = STAT(ARC_HEAT);
 
@@ -837,7 +1149,7 @@ void HUD_Crosshair()
 
 
                                // handle the values
-                               if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX.m_id && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
+                               if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
                                {
                                        if (vortex_chargepool || use_vortex_chargepool) {
                                                use_vortex_chargepool = 1;
@@ -857,16 +1169,16 @@ void HUD_Crosshair()
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring_nexgun.tga";
                                }
-                               else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER.m_id && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
+                               else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
                                {
-                                       ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
+                                       ring_value = bound(0, STAT(LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
                                        ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
                                }
-                               else if (activeweapon == WEP_HAGAR.m_id && getstati(STAT_HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
+                               else if (activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
                                {
-                                       ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / hagar_maxrockets, 1);
+                                       ring_value = bound(0, STAT(HAGAR_LOAD) / hagar_maxrockets, 1);
                                        ring_alpha = autocvar_crosshair_ring_hagar_alpha;
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
@@ -887,12 +1199,12 @@ void HUD_Crosshair()
 
                                        // Note: This is to stop Taoki from complaining that the image doesn't match all potential balances.
                                        // if a new image for another weapon is added, add the code (and its respective file/value) here
-                                       if ((activeweapon == WEP_RIFLE.m_id) && (weapon_clipsize == 80))
+                                       if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
                                                ring_image = "gfx/crosshair_ring_rifle.tga";
                                        else
                                                ring_image = "gfx/crosshair_ring.tga";
                                }
-                               else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && activeweapon == WEP_ARC.m_id )
+                               else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && activeweapon == WEP_ARC )
                                {
                                        ring_value = arc_heat;
                                        ring_alpha = (1-arc_heat)*autocvar_crosshair_ring_arc_cold_alpha +
@@ -1012,20 +1324,20 @@ void HUD_Draw()
                rgb = MUTATOR_ARGV(0, vector);
                a = MUTATOR_ARGV(0, float);
        }
-       else if(getstati(STAT_FROZEN))
+       else if(STAT(FROZEN))
        {
-               rgb = ((getstatf(STAT_REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * getstatf(STAT_REVIVE_PROGRESS)) + ('0 1 1' * getstatf(STAT_REVIVE_PROGRESS) * -1)) : '0.25 0.90 1');
+               rgb = ((STAT(REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * STAT(REVIVE_PROGRESS)) + ('0 1 1' * STAT(REVIVE_PROGRESS) * -1)) : '0.25 0.90 1');
        }
        drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, rgb, autocvar_hud_colorflash_alpha * a, DRAWFLAG_ADDITIVE);
        if(!intermission)
-       if(getstatf(STAT_NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
+       if(STAT(NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
        {
-               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * getstatf(STAT_NADE_TIMER)) - ('0 1 1' * getstatf(STAT_NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * STAT(NADE_TIMER)) - ('0 1 1' * STAT(NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
                drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
        }
-       else if(getstatf(STAT_REVIVE_PROGRESS))
+       else if(STAT(REVIVE_PROGRESS))
        {
-               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
                drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
        }
 
@@ -1071,7 +1383,7 @@ void CSQC_UpdateView(float w, float h)
        ++framecount;
 
        stats_get();
-       hud = getstati(STAT_HUD);
+       hud = STAT(HUD);
 
        if(hud != HUD_NORMAL && lasthud == HUD_NORMAL)
                vh_notice_time = time + autocvar_cl_vehicles_notify_time;
@@ -1109,7 +1421,7 @@ void CSQC_UpdateView(float w, float h)
                current_player = player_localentnum - 1;
        else // then player_localentnum is the vehicle I'm driving
                current_player = player_localnum;
-       myteam = GetPlayerColor(current_player);
+       myteam = entcs_GetTeam(current_player);
 
        if(myteam != prev_myteam)
        {
@@ -1118,7 +1430,7 @@ void CSQC_UpdateView(float w, float h)
                prev_myteam = myteam;
        }
 
-       ticrate = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+       ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
 
        float is_dead = (getstati(STAT_HEALTH) <= 0);
 
@@ -1142,7 +1454,7 @@ void CSQC_UpdateView(float w, float h)
        if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
        {
                float vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
-               float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && getstati(STAT_ROUNDLOST));
+               float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && STAT(ROUNDLOST));
                entity gen = world;
 
                if(ons_roundlost)
@@ -1395,10 +1707,12 @@ void CSQC_UpdateView(float w, float h)
        ColorTranslateMode = autocvar_cl_stripcolorcodes;
 
        // currently switching-to weapon (for crosshair)
-       switchingweapon = getstati(STAT_SWITCHINGWEAPON);
+       switchingweapon = Weapons_from(STAT(SWITCHINGWEAPON));
 
        // actually active weapon (for zoom)
-       activeweapon = getstati(STAT_ACTIVEWEAPON);
+       activeweapon = Weapons_from(getstati(STAT_ACTIVEWEAPON));
+
+       switchweapon = Weapons_from(STAT(SWITCHWEAPON));
 
        f = (serverflags & SERVERFLAG_TEAMPLAY);
        if(f != teamplay)
@@ -1427,7 +1741,7 @@ void CSQC_UpdateView(float w, float h)
        {
                last_activeweapon = activeweapon;
 
-               e = get_weaponinfo(activeweapon);
+               e = activeweapon;
                if(e.netname != "")
                        localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
                else
@@ -1560,7 +1874,7 @@ void CSQC_UpdateView(float w, float h)
 
        if(autocvar_cl_reticle)
        {
-               Weapon wep = get_weaponinfo(activeweapon);
+               Weapon wep = activeweapon;
                // Draw the aiming reticle for weapons that use it
                // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
                // It must be a persisted float for fading out to work properly (you let go of the zoom button for
@@ -1684,7 +1998,7 @@ void CSQC_UpdateView(float w, float h)
                }
        }
 
-       if(autocvar_hud_damage && !getstati(STAT_FROZEN))
+       if(autocvar_hud_damage && !STAT(FROZEN))
        {
                splash_size.x = max(vid_conwidth, vid_conheight);
                splash_size.y = max(vid_conwidth, vid_conheight);
index 1591bad96b5ccba33b54f72a29acbb93cf1bad3f..2100c3f5fd41d4680937b0adfc63ff7c10cf642e 100644 (file)
@@ -280,46 +280,46 @@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool isnew)
                self.traileffect = 0;
                switch (self.cnt)
                {
-                       #define CASE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
-                       CASE(ELECTRO)            self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
-                       CASE(ROCKET)             self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
-                       CASE(CRYLINK)            self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
-                       CASE(CRYLINK_BOUNCING)   self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
-                       CASE(ELECTRO_BEAM)       self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
-                       CASE(GRENADE)            self.traileffect = EFFECT_TR_GRENADE.m_id; break;
-                       CASE(GRENADE_BOUNCING)   self.traileffect = EFFECT_TR_GRENADE.m_id; break;
-                       CASE(MINE)               self.traileffect = EFFECT_TR_GRENADE.m_id; break;
-                       CASE(BLASTER)            self.traileffect = EFFECT_Null.m_id; break;
-                       CASE(HLAC)               self.traileffect = EFFECT_Null.m_id; break;
-                       CASE(PORTO_RED)          self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
-                       CASE(PORTO_BLUE)         self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
-                       CASE(HOOKBOMB)           self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
-                       CASE(HAGAR)              self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
-                       CASE(HAGAR_BOUNCING)     self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
-                       CASE(FIREBALL)           self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
-                       CASE(FIREMINE)           self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
-                       CASE(TAG)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
-                       CASE(FLAC)               self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
-                       CASE(SEEKER)             self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
-
-                       CASE(MAGE_SPIKE)         self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
-                       CASE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
-
-                       CASE(RAPTORBOMB)         self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
-                       CASE(RAPTORBOMBLET)      self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
-                       CASE(RAPTORCANNON)       self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
-
-                       CASE(SPIDERROCKET)       self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
-                       CASE(WAKIROCKET)         self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
-                       CASE(WAKICANNON)         self.traileffect = EFFECT_Null.m_id; break;
-
-                       CASE(BUMBLE_GUN)         self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
-                       CASE(BUMBLE_BEAM)        self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
-
-                       CASE(RPC)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
-
-                       CASE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
-#undef CASE
+                       #define HANDLE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
+                       HANDLE(ELECTRO)            self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+                       HANDLE(ROCKET)             self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
+                       HANDLE(CRYLINK)            self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+                       HANDLE(CRYLINK_BOUNCING)   self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+                       HANDLE(ELECTRO_BEAM)       self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+                       HANDLE(GRENADE)            self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+                       HANDLE(GRENADE_BOUNCING)   self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+                       HANDLE(MINE)               self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+                       HANDLE(BLASTER)            self.traileffect = EFFECT_Null.m_id; break;
+                       HANDLE(HLAC)               self.traileffect = EFFECT_Null.m_id; break;
+                       HANDLE(PORTO_RED)          self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+                       HANDLE(PORTO_BLUE)         self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+                       HANDLE(HOOKBOMB)           self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
+                       HANDLE(HAGAR)              self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+                       HANDLE(HAGAR_BOUNCING)     self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+                       HANDLE(FIREBALL)           self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
+                       HANDLE(FIREMINE)           self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
+                       HANDLE(TAG)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+                       HANDLE(FLAC)               self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
+                       HANDLE(SEEKER)             self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
+
+                       HANDLE(MAGE_SPIKE)         self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
+                       HANDLE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+                       HANDLE(RAPTORBOMB)         self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+                       HANDLE(RAPTORBOMBLET)      self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+                       HANDLE(RAPTORCANNON)       self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+
+                       HANDLE(SPIDERROCKET)       self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
+                       HANDLE(WAKIROCKET)         self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
+                       HANDLE(WAKICANNON)         self.traileffect = EFFECT_Null.m_id; break;
+
+                       HANDLE(BUMBLE_GUN)         self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+                       HANDLE(BUMBLE_BEAM)        self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+                       HANDLE(RPC)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+
+                       HANDLE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
+#undef HANDLE
                        default:
                                if (MUTATOR_CALLHOOK(Ent_Projectile, self))
                                        break;
diff --git a/qcsrc/common/anim.qc b/qcsrc/common/anim.qc
new file mode 100644 (file)
index 0000000..6a4dbe5
--- /dev/null
@@ -0,0 +1,49 @@
+#include "anim.qh"
+
+/**
+ * @param anim x = startframe, y = numframes, z = framerate
+ */
+void anim_set(entity e, vector anim, bool looping, bool override, bool restart)
+{
+       if (!anim) return;  // no animation was given to us! We can't use this.
+
+       if (anim.x == e.animstate_startframe)
+       {
+               if (anim.y == e.animstate_numframes)
+               {
+                       if (anim.z == e.animstate_framerate)
+                       {
+                               if (!restart) return;
+                               if (anim.y == 1)  // ZYM animation
+                                       BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
+                       }
+               }
+       }
+       e.animstate_startframe = anim.x;
+       e.animstate_numframes = anim.y;
+       e.animstate_framerate = anim.z;
+       e.animstate_starttime = time - 0.1 * frametime;  // shift it a little bit into the past to prevent float inaccuracy hiccups
+       e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
+       e.animstate_looping = looping;
+       e.animstate_override = override;
+       e.frame = e.animstate_startframe;
+       e.frame1time = time;
+}
+
+/**
+ * Update e.frame based on its animstate relative to time
+ */
+void anim_update(entity e)
+{
+       if (time >= e.animstate_endtime)
+       {
+               if (e.animstate_looping)
+               {
+                       e.animstate_starttime = e.animstate_endtime;
+                       e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
+               }
+               e.animstate_override = false;
+       }
+       float frameofs = bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1);
+       e.frame = e.animstate_startframe + frameofs;
+}
diff --git a/qcsrc/common/anim.qh b/qcsrc/common/anim.qh
new file mode 100644 (file)
index 0000000..acf6735
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef ANIM_H
+#define ANIM_H
+
+// begin engine fields
+
+/** primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4) */
+.float frame;
+/** secondary framegroup animation (strength = lerpfrac) */
+.float frame2;
+/** tertiary framegroup animation (strength = lerpfrac3) */
+.float frame3;
+/** quaternary framegroup animation (strength = lerpfrac4) */
+.float frame4;
+
+/** strength of framegroup blend */
+.float lerpfrac;
+/** strength of framegroup blend */
+.float lerpfrac3;
+/** strength of framegroup blend */
+.float lerpfrac4;
+
+/** start time of framegroup animation */
+.float frame1time;
+/** start time of framegroup animation */
+.float frame2time;
+/** start time of framegroup animation */
+.float frame3time;
+/** start time of framegroup animation */
+.float frame4time;
+
+// end engine fields
+
+// player animation state
+
+.int animstate_startframe;
+.int animstate_numframes;
+.float animstate_framerate;
+.float animstate_starttime;
+.float animstate_endtime;
+/** whether to repeat */
+.bool animstate_looping;
+/** true for one cycle, then changed to false */
+.bool animstate_override;
+
+void anim_set(entity e, vector anim, bool looping, bool override, bool restart);
+#define setanim(...) anim_set(__VA_ARGS__)
+void anim_update(entity e);
+#define updateanim(...) anim_update(__VA_ARGS__)
+
+#endif
index 1ea5a8bff56aa213d54992e529f7030bc0a65efc..96368bd15d2901f6d141d5e499bb15fad5fbe5e8 100644 (file)
@@ -238,22 +238,12 @@ vector autocvar_sv_player_headsize = '24 24 12';
 
 
 // not so constant
-#ifdef SVQC
-#define PL_VIEW_OFS autocvar_sv_player_viewoffset
-#define PL_MIN autocvar_sv_player_mins
-#define PL_MAX autocvar_sv_player_maxs
-#define PL_CROUCH_VIEW_OFS autocvar_sv_player_crouch_viewoffset
-#define PL_CROUCH_MIN autocvar_sv_player_crouch_mins
-#define PL_CROUCH_MAX autocvar_sv_player_crouch_maxs
-#define PL_HEAD autocvar_sv_player_headsize
-#elif defined(CSQC)
-#define PL_VIEW_OFS vec3(getstatf(STAT_PL_VIEW_OFS1), getstatf(STAT_PL_VIEW_OFS2), getstatf(STAT_PL_VIEW_OFS3))
-#define PL_MIN vec3(getstatf(STAT_PL_MIN1), getstatf(STAT_PL_MIN2), getstatf(STAT_PL_MIN3))
-#define PL_MAX vec3(getstatf(STAT_PL_MAX1), getstatf(STAT_PL_MAX2), getstatf(STAT_PL_MAX3))
-#define PL_CROUCH_VIEW_OFS vec3(getstatf(STAT_PL_CROUCH_VIEW_OFS1), getstatf(STAT_PL_CROUCH_VIEW_OFS2), getstatf(STAT_PL_CROUCH_VIEW_OFS3))
-#define PL_CROUCH_MIN vec3(getstatf(STAT_PL_CROUCH_MIN1), getstatf(STAT_PL_CROUCH_MIN2), getstatf(STAT_PL_CROUCH_MIN3))
-#define PL_CROUCH_MAX vec3(getstatf(STAT_PL_CROUCH_MAX1), getstatf(STAT_PL_CROUCH_MAX2), getstatf(STAT_PL_CROUCH_MAX3))
-#endif
+#define PL_VIEW_OFS STAT(PL_VIEW_OFS, NULL)
+#define PL_CROUCH_VIEW_OFS STAT(PL_CROUCH_VIEW_OFS, NULL)
+#define PL_MIN STAT(PL_MIN, NULL)
+#define PL_CROUCH_MIN STAT(PL_CROUCH_MIN, NULL)
+#define PL_MAX STAT(PL_MAX, NULL)
+#define PL_CROUCH_MAX STAT(PL_CROUCH_MAX, NULL)
 
 // a bit more constant
 const vector PL_MAX_CONST = '16 16 45';
index d86efb5e979f7bf81ba8b44c2a049a6a8c609d38..9f9fa43f30f8ec2363fce01e214345dfa5aa0abc 100644 (file)
 # define TAG_VIEWLOC_NAME tag_networkviewloc
 # define TAG_VIEWLOC_TYPE int
 .float tag_networkviewloc;
+
+# define MOVETYPE_NAME move_movetype
 #else
 # define TAG_ENTITY_NAME tag_entity
 # define TAG_ENTITY_TYPE entity
 
 # define TAG_VIEWLOC_NAME viewloc
 # define TAG_VIEWLOC_TYPE entity
+
+# define MOVETYPE_NAME movetype
 #endif
 
 // new fields
@@ -63,7 +67,8 @@
        CSQCMODEL_PROPERTY_SCALED(BIT(12), float, ReadByte, WriteByte, scale, 16, 0, 255) \
        CSQCMODEL_PROPERTY(BIT(13), int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
        CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME) \
-       CSQCMODEL_PROPERTY(BIT(15), int, ReadByte, WriteByte, multijump_count)
+       CSQCMODEL_PROPERTY(BIT(15), int, ReadByte, WriteByte, multijump_count) \
+       CSQCMODEL_PROPERTY(BIT(16), int, ReadByte, WriteByte, MOVETYPE_NAME)
 // TODO get rid of colormod/glowmod here, find good solution for vortex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
 
 // add hook function calls here
index dcf64b11f3d635b6dac5224de9d93977ac87585c..3c953bcf9d4756ddda33d8cd807fdc005476e03b 100644 (file)
@@ -40,7 +40,7 @@ const int DT_FIRST = BIT(13);
 #define DEATH_ISVEHICLE(t)      (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)).death_msgextra == "vehicle")
 #define DEATH_ISTURRET(t)       (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)).death_msgextra == "turret")
 #define DEATH_ISMONSTER(t)      (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)).death_msgextra == "monster")
-#define DEATH_WEAPONOF(t)       (DEATH_ISSPECIAL(t) ? WEP_Null : get_weaponinfo((t) & DEATH_WEAPONMASK))
+#define DEATH_WEAPONOF(t)       (DEATH_ISSPECIAL(t) ? WEP_Null : Weapons_from((t) & DEATH_WEAPONMASK))
 #define DEATH_ISWEAPON(t, w)    (DEATH_WEAPONOF(t) == (w))
 
 string Deathtype_Name(int deathtype);
index 76f582ee7720c8e59bc4c8ec0e8266076c0169a0..5ead52479d9efda26f400c984c566edb1b23060e 100644 (file)
@@ -43,6 +43,7 @@ REGISTER_NET_TEMP(net_debug)
 bool autocvar_debugdraw;
 
 #ifdef CSQC
+       string autocvar_debugdraw_filter;
        .int debugdraw_last;
        vector project_3d_to_2d(vector vec);
        void Debug_Draw()
@@ -59,6 +60,7 @@ bool autocvar_debugdraw;
                                if (e.debugdraw_last == debugdraw_frame) continue;
                                e.debugdraw_last = debugdraw_frame;
                                vector rgb = (e.debug) ? '0 0 1' : '1 0 0';
+                               if (autocvar_debugdraw_filter != "" && !strhasword(autocvar_debugdraw_filter, e.classname)) continue;
                                if (is_pure(e))
                                {
                                        if (autocvar_debugdraw < 2) continue;
@@ -109,4 +111,26 @@ bool autocvar_debugdraw;
        }
 #endif
 
+GENERIC_COMMAND(bufstr_get, "Examine a string buffer object")
+{
+       switch (request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                   int bufhandle = stof(argv(1));
+                   int string_index = stof(argv(2));
+                       string s = bufstr_get(bufhandle, string_index);
+                       LOG_INFOF("%s\n", s);
+                       return;
+               }
+
+               default:
+               case CMD_REQUEST_USAGE:
+               {
+                       LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " bufstr_get bufhandle string_index"));
+                       return;
+               }
+       }
+}
+
 #endif
index d920bd139eab195a99d7013db532e17d1a0bc98e..6e0e461f2b8e707ce776ec07b57e964efe3be9d4 100644 (file)
                 */
                void globalsound(int channel, entity from, entity gs, float r, int chan, float vol, float atten)
                {
+                       assert(IS_PLAYER(from), eprint(from));
                        if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return;
                        WriteHeader(channel, globalsound);
                        WriteByte(channel, gs.m_id);
                        WriteByte(channel, r * 255);
                        WriteByte(channel, etof(from));
-                       WriteByte(channel, fabs(chan));
+                       WriteByte(channel, chan);
                        WriteByte(channel, floor(vol * 255));
                        WriteByte(channel, floor(atten * 64));
                        entcs_force_origin(from);
                */
                void playersound(int channel, entity from, entity ps, float r, int chan, float vol, float atten)
                {
+                       assert(IS_PLAYER(from), eprint(from));
                        if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return;
                        WriteHeader(channel, playersound);
                        WriteByte(channel, ps.m_id);
                        WriteByte(channel, r * 255);
                        WriteByte(channel, etof(from));
-                       WriteByte(channel, fabs(chan));
+                       WriteByte(channel, chan);
                        WriteByte(channel, floor(vol * 255));
                        WriteByte(channel, floor(atten * 64));
                        entcs_force_origin(from);
@@ -70,6 +72,7 @@
                        int who = ReadByte();
                        entity e = entcs_receiver(who - 1);
                        int chan = ReadByte();
+                       chan = (chan & BIT(7) ? -1 : 1) * (chan & BITS(7));
                        float vol = ReadByte() / 255;
                        float atten = ReadByte() / 64;
                        vector o;
                        }
                        else
                        {
-                               entity e = new(globalsound);
-                               e.origin = o;
+                               // Can this happen?
+                               LOG_WARNINGF("Missing entcs data for player %d\n", who);
                                sound8(e, o, chan, sample, vol, atten, 0, 0);
-                               remove(e);  // debug with: e.think = SUB_Remove; e.nextthink = time + 1;
                        }
                        return true;
                }
                        string s = e.(ps.m_playersoundfld);
                        string sample = GlobalSound_sample(s, r);
                        int chan = ReadByte();
+                       chan = (chan & BIT(7) ? -1 : 1) * (chan & BITS(7));
                        float vol = ReadByte() / 255;
                        float atten = ReadByte() / 64;
                        vector o;
                        }
                        else
                        {
-                               LOG_WARNINGF("Missing entcs data for player %d\n", who);
                                // Can this happen?
-                               entity e = new(playersound);
-                               e.origin = o;
+                               LOG_WARNINGF("Missing entcs data for player %d\n", who);
                                sound8(e, o, chan, sample, vol, atten, 0, 0);
-                               remove(e);  // debug with: e.think = SUB_Remove; e.nextthink = time + 1;
                        }
                        return true;
                }
 
        #ifdef SVQC
 
-               void _GlobalSound(entity gs, entity ps, string sample, int chan, int voicetype, bool fake)
+               bool autocvar_g_debug_globalsounds;
+
+               void _GlobalSound(entity this, entity gs, entity ps, string sample, int chan, int voicetype, bool fake)
                {
-                       SELFPARAM();
                        if (gs == NULL && ps == NULL && sample == "") return;
                        float r = random();
                        if (sample != "") sample = GlobalSound_sample(sample, r);
                                        }
                                        else
                                        {
-                                               if (gs) globalsound(MSG_ALL, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+                                               if (gs)
+                                               {
+                                                       if(autocvar_g_debug_globalsounds)
+                                                               globalsound(MSG_ALL, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+                                                       else
+                                                               _sound(this, chan, GlobalSound_sample(gs.m_globalsoundstr, r), VOL_BASE, ATTEN_NORM);
+                                               }
                                                else if (ps) playersound(MSG_ALL, this, ps, r, chan, VOL_BASE, ATTEN_NORM);
                                                else _sound(this, chan, sample, VOL_BASE, ATTEN_NORM);
                                        }
index 4b86da5c8f6fda1cb51c139cf76ef1e7ad08bbd3..892d3d078b3dfb523f41c6bb59ea44d4eb8c0ec6 100644 (file)
@@ -121,11 +121,11 @@ void PrecachePlayerSounds(string f);
 
 #ifdef SVQC
 
-       void _GlobalSound(entity gs, entity ps, string sample, float chan, float voicetype, bool fake);
-       #define GlobalSound(def, chan, voicetype) _GlobalSound(def, NULL, string_null, chan, voicetype, false)
-       #define GlobalSound_string(def, chan, voicetype) _GlobalSound(NULL, NULL, def, chan, voicetype, false)
-       #define PlayerSound(def, chan, voicetype) _GlobalSound(NULL, def, string_null, chan, voicetype, false)
-       #define VoiceMessage(def, msg) \
+       void _GlobalSound(entity this, entity gs, entity ps, string sample, float chan, float voicetype, bool fake);
+       #define GlobalSound(this, def, chan, voicetype) _GlobalSound(this, def, NULL, string_null, chan, voicetype, false)
+       #define GlobalSound_string(this, def, chan, voicetype) _GlobalSound(this, NULL, NULL, def, chan, voicetype, false)
+       #define PlayerSound(thise, def, chan, voicetype) _GlobalSound(this, NULL, def, string_null, chan, voicetype, false)
+       #define VoiceMessage(this, def, msg) \
                do \
                { \
                        entity VM = def; \
@@ -136,7 +136,7 @@ void PrecachePlayerSounds(string f);
                        if (IS_SPEC(this) || IS_OBSERVER(this) || flood < 0) fake = true; \
                        else if (flood > 0) fake = false; \
                        else break; \
-                       _GlobalSound(NULL, VM, string_null, CH_VOICE, voicetype, fake); \
+                       _GlobalSound(this, NULL, VM, string_null, CH_VOICE, voicetype, fake); \
                } \
                while (0)
 
index c07fad0d5242fc08dc7a9e1c26b1d79d98c6bee3..4aa31ed01e8d02d119331b6cc2245ec998ba5df6 100644 (file)
@@ -3,36 +3,36 @@
 // #define PROP(public, fld, sv, cl)
 #define ENTCS_NETPROPS(PROP) \
        PROP(true, sv_entnum, \
-       { WriteByte(MSG_ENTITY, etof(player) - 1); }, \
+       { WriteByte(chan, etof(player) - 1); }, \
        { this.sv_entnum = ReadByte(); }) \
     \
        PROP(false, origin, \
-       { WriteShort(MSG_ENTITY, this.origin.x);  WriteShort(MSG_ENTITY, this.origin.y); \
-         WriteShort(MSG_ENTITY, this.origin.z); }, \
+       { WriteShort(chan, this.origin.x);  WriteShort(chan, this.origin.y); \
+         WriteShort(chan, this.origin.z); }, \
        { this.has_sv_origin = true; vector v; v.x = ReadShort(); v.y = ReadShort(); v.z = ReadShort(); setorigin(this, v); }) \
     \
        PROP(false, angles_y, \
-       { WriteByte(MSG_ENTITY, this.angles.y / 360 * 256); }, \
+       { WriteByte(chan, this.angles.y / 360 * 256); }, \
        { vector v = '0 0 0'; v.y = ReadByte() / 256 * 360; this.angles = v; }) \
     \
        PROP(false, health, \
-       { WriteByte(MSG_ENTITY, this.health / 10);  /* FIXME: use a better scale? */ }, \
+       { WriteByte(chan, this.health / 10);  /* FIXME: use a better scale? */ }, \
        { this.healthvalue = ReadByte() * 10; }) \
     \
        PROP(false, armorvalue, \
-       { WriteByte(MSG_ENTITY, this.armorvalue / 10);  /* FIXME: use a better scale? */ }, \
+       { WriteByte(chan, this.armorvalue / 10);  /* FIXME: use a better scale? */ }, \
        { this.armorvalue = ReadByte() * 10; }) \
     \
        PROP(true, netname, \
-       { WriteString(MSG_ENTITY, this.netname); }, \
+       { WriteString(chan, this.netname); }, \
        { if (this.netname) strunzone(this.netname); this.netname = strzone(ReadString()); }) \
     \
        PROP(true, model, \
-       { WriteString(MSG_ENTITY, this.model); }, \
+       { WriteString(chan, this.model); }, \
        { if (this.model) strunzone(this.model); this.model = strzone(ReadString()); }) \
     \
        PROP(true, skin, \
-       { WriteByte(MSG_ENTITY, this.skin); }, \
+       { WriteByte(chan, this.skin); }, \
        { this.skin = ReadByte(); }) \
     \
        /**/
@@ -49,7 +49,7 @@
                if (i >= BITS(16 - 1)) LOG_FATAL("Exceeded ENTCS_NETPROPS limit");
        }
 
-       bool entcs_send(entity this, entity to, int sf)
+       bool _entcs_send(entity this, entity to, int sf, int chan)
        {
                entity player = this.owner;
                sf |= BIT(0) | BIT(1);
                this.m_forceupdate = 0;
                bool valid =
                    IS_PLAYER(player)             // player must be active
-                   && player.deadflag == DEAD_NO // player must be alive
                    || player == to               // player is self
                ;
                if (!valid) sf = 0;
-               WriteHeader(MSG_ENTITY, ENT_CLIENT_ENTCS);
-               WriteShort(MSG_ENTITY, sf);
+               if (chan == MSG_ENTITY)
+                       WriteHeader(chan, ENT_CLIENT_ENTCS);
+               else
+                       WriteHeader(chan, CLIENT_ENTCS);
+               WriteByte(chan, etof(player) - 1);
+               WriteShort(chan, sf);
                int i = 1;
                #define X(public, fld, sv, cl) { if (sf & BIT(i)) sv; } i += 1;
                ENTCS_NETPROPS(X);
                return true;
        }
 
+       bool entcs_send(entity this, entity to, int sf)
+       {
+               return _entcs_send(this, to, sf, MSG_ENTITY);
+       }
+
        void entcs_think()
        {
                SELFPARAM();
                e.think = entcs_think;
                e.nextthink = time;
                Net_LinkEntity(e, false, 0, entcs_send);
+               if (!IS_REAL_CLIENT(player)) return;
+               FOR_EACH_CLIENT(e)
+               {
+                       assert(e.entcs);
+                       _entcs_send(e.entcs, msg_entity = player, BITS(23), MSG_ONE);
+               }
        }
 
        void entcs_detach(entity player)
        void Ent_RemoveEntCS()
        {
                SELFPARAM();
-               entcs_receiver(this.sv_entnum, NULL);
+               int n = this.sv_entnum;
+               entity e = entcs_receiver(n);
+               entcs_receiver(n, NULL);
+               if (e != this) remove(e);
        }
 
        void entcs_think()
        {
                SELFPARAM();
-               this.nextthink = time;
                entity e = CSQCModel_server2csqc(this.sv_entnum);
-               bool exists = e != NULL;
-               if (exists)
+               if (e == NULL)
                {
-                       this.has_origin = true;
-                       this.origin = e.origin;
-                       // `cl_forceplayermodels 1` sounds will be wrong until the player has been in the PVS, but so be it
-                       if (this.model != e.model)
-                       {
-                               if (this.model) strunzone(this.model);
-                               this.model = strzone(e.model);
-                       }
+                       this.has_origin = this.has_sv_origin;
+                       return;
                }
-               else
+               this.has_origin = true;
+               this.origin = e.origin;
+               // `cl_forceplayermodels 1` sounds will be wrong until the player has been in the PVS, but so be it
+               if (this.model != e.model)
                {
-                       this.has_origin = this.has_sv_origin;
+                       if (this.model) strunzone(this.model);
+                       this.model = strzone(e.model);
                }
        }
 
-       NET_HANDLE(ENT_CLIENT_ENTCS, bool isnew)
+       bool ReadEntcs(entity this)
        {
-               if (isnew)
+               int n = ReadByte();
+               entity e = entcs_receiver(n);
+               if (e == NULL)
                {
-                       make_pure(this);
-                       this.classname = "entcs_receiver";
-                       this.entremove = Ent_RemoveEntCS;
-                       this.think = entcs_think;
-                       this.nextthink = time;
+                       if (this)
+                       {
+                               e = this;
+                       }
+                       else
+                       {
+                               e = new(entcs_receiver);
+                               make_pure(e);
+                       }
+                       e.sv_entnum = n;
+                       e.think = entcs_think;
+                       entcs_receiver(n, e);
+               }
+               else if (this && e != this)
+               {
+                       this.classname = "entcs_gc";
+                       this.sv_entnum = n;
                }
+               this = e;
                InterpolateOrigin_Undo(this);
+               this.sv_entnum = n;
                int sf = ReadShort();
                this.has_sv_origin = false;
                this.m_entcs_private = boolean(sf & BIT(0));
                #define X(public, fld, sv, cl) { if (sf & BIT(i)) cl; } i += 1;
                ENTCS_NETPROPS(X);
        #undef X
-               entcs_receiver(this.sv_entnum, this);
                this.iflags |= IFLAG_ORIGIN;
                InterpolateOrigin_Note(this);
+               WITH(entity, self, this, this.think());
                return true;
        }
 
+       NET_HANDLE(ENT_CLIENT_ENTCS, bool isnew)
+       {
+               if (isnew)
+               {
+                       make_pure(this);
+                       this.classname = "entcs_receiver";
+                       this.entremove = Ent_RemoveEntCS;
+               }
+               return ReadEntcs(this);
+       }
+
+       NET_HANDLE(CLIENT_ENTCS, bool isnew)
+       {
+               return ReadEntcs(NULL);
+       }
+
 #endif
index 7f773527b073f34b85907ee481e4442bd38f28fd..8122ccdc0ee543ad913594b6384c697efe665971 100644 (file)
@@ -2,6 +2,7 @@
 #define ENT_CS_H
 
 REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
+REGISTER_NET_TEMP(CLIENT_ENTCS)
 
 /** True when private information such as origin is available */
 .bool m_entcs_private;
@@ -40,25 +41,34 @@ REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
 
 #ifdef CSQC
 
-       AL_declare(_entcs);
+       ArrayList _entcs;
        STATIC_INIT(_entcs)
        {
-               AL_init(_entcs, 255, NULL, e);  // 255 is the engine limit on maxclients
+               AL_NEW(_entcs, 255, NULL, e);  // 255 is the engine limit on maxclients
        }
        SHUTDOWN(_entcs)
        {
-               AL_delete(_entcs);
+               AL_DELETE(_entcs);
        }
        #define entcs_receiver(...) EVAL(OVERLOAD(entcs_receiver, __VA_ARGS__))
        #define entcs_receiver_1(i) AL_gete(_entcs, i)
        #define entcs_receiver_2(i, v) AL_sete(_entcs, i, v)
        #define entcs_is_self(e) ((e).sv_entnum == player_localentnum - 1)
 
+       /**
+     * @param i zero indexed player
+     */
+       bool entcs_IsSpectating(int i)
+       {
+               bool unconnected = !playerslots[i].gotscores;
+               return unconnected || stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR;
+       }
+
        /**
        * @param i zero indexed player
        * @returns 0 if not teamplay
        */
-       int GetPlayerColorForce(int i)
+       int entcs_GetTeamColor(int i)
        {
                return (!teamplay) ? 0 : stof(getplayerkeyvalue(i, "colors")) & 15;
        }
@@ -67,17 +77,15 @@ REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
        * @param i zero indexed player
        * @returns 0 if not teamplay | NUM_TEAM_##N | NUM_SPECTATOR
        */
-       int GetPlayerColor(int i)
+       int entcs_GetTeam(int i)
        {
-               bool unconnected = !playerslots[i].gotscores;
-               bool spec = unconnected || stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR;
-               return (spec) ? NUM_SPECTATOR : GetPlayerColorForce(i);
+               return entcs_IsSpectating(i) ? NUM_SPECTATOR : entcs_GetTeamColor(i);
        }
 
        /**
        * @param i zero indexed player
        */
-       string GetPlayerName(int i)
+       string entcs_GetName(int i)
        {
                return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
        }
@@ -92,7 +100,7 @@ REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
     /**
      * @param i zero indexed player
      */
-       float getplayeralpha(int i)
+       float entcs_GetAlpha(int i)
        {
                entity e = CSQCModel_server2csqc(i);
                return e ? e.alpha : 1;
@@ -101,7 +109,7 @@ REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
     /**
      * @param i zero indexed player
      */
-       vector getcsqcplayercolor(int i)
+       vector entcs_GetColor(int i)
        {
                entity e = CSQCModel_server2csqc(i);
                return (!e || e.colormap <= 0)
@@ -115,7 +123,7 @@ REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
     /**
      * @param i zero indexed player
      */
-       bool getplayerisdead(int i)
+       bool entcs_IsDead(int i)
        {
                entity e = CSQCModel_server2csqc(i);
                return e ? e.csqcmodel_isdead : false;
index 1850b460c7675a5a9a2499f6652e5f7b43aa9dbe..cc418df5e4da015f0a5600a41c6b66f5232ed58d 100644 (file)
@@ -2,7 +2,7 @@
 
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-.float metertime;
+.float metertime = _STAT(NB_METERSTART);
 
 int autocvar_g_nexball_goalleadlimit;
 #define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
@@ -1072,7 +1072,6 @@ REGISTER_MUTATOR(nb, g_nexball)
                if(g_nexball_meter_period <= 0)
                        g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
                g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
-               addstat(STAT_NB_METERSTART, AS_FLOAT, metertime);
 
                // General settings
                /*
index ae62e5db797d2a22cb9467fc41ff7e431d2f50e3..9cafd1a23a60c070906bac2c4fc0de68684264ed 100644 (file)
@@ -76,7 +76,7 @@ bool ons_stalemate;
 
 .float teleport_antispam;
 
-.bool ons_roundlost;
+.bool ons_roundlost = _STAT(ROUNDLOST);
 
 // waypoint sprites
 .entity bot_basewaypoint; // generator waypointsprite
@@ -1342,7 +1342,7 @@ void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float s
        for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
        {
                // Find weapon
-               if(self.weapons & WepSet_FromWeapon(i))
+               if(self.weapons & WepSet_FromWeapon(Weapons_from(i)))
                if(++c>=4)
                        break;
        }
@@ -2318,8 +2318,6 @@ void ons_Initialize()
        g_onslaught = true;
        ons_captureshield_force = autocvar_g_onslaught_shield_force;
 
-       addstat(STAT_ROUNDLOST, AS_INT, ons_roundlost);
-
        InitializeEntity(world, ons_DelayedInit, INITPRIO_GAMETYPE);
 }
 
index 3ea50caad3d0554bb5f1b7b4e389b29bf6052d6b..a9f4a4f4cfab763ce23a22572b74b964bacb4a26 100644 (file)
@@ -212,7 +212,7 @@ NET_HANDLE(ENT_CLIENT_MINIGAME, bool isnew)
                        minigame_read_owner();
                        float ent = ReadLong();
                        self.minigame_playerslot = ent;
-                       LOG_DEBUG("Player: ",GetPlayerName(ent-1),"\n");
+                       LOG_DEBUG("Player: ",entcs_GetName(ent-1),"\n");
 
                        activate = (ent == player_localnum+1 && self.owner && self.owner != active_minigame);
 
index 822aff3fad4439a129a97ea3413f239d52dcf417..e93c95ca6077bed5935373c47bf0e1426f4c3315 100644 (file)
@@ -283,11 +283,11 @@ void HUD_MinigameMenu_ClickInvite()
                entity prev = self;
                for(int i = 0; i < maxclients; ++i)
                {
-                       if ( player_localnum != i && playerslots[i] && GetPlayerName(i) != "" &&
+                       if ( player_localnum != i && playerslots[i] && entcs_GetName(i) != "" &&
                                !findfloat(world,minigame_playerslot,i+1) && playerslots[i].ping )
                        {
                                e = HUD_MinigameMenu_SpawnSubEntry(
-                                       strzone(GetPlayerName(i)), HUD_MinigameMenu_ClickInvite_Entry,
+                                       strzone(entcs_GetName(i)), HUD_MinigameMenu_ClickInvite_Entry,
                                        self );
                                e.flags |= 1;
                                e.netname = strzone(ftos(i+1));
index a311005b7fd5ebb377cba2f9c08533d4d60be6ec..ed84b6469c33c56b79eda5592d92c51206fe0228 100644 (file)
@@ -854,7 +854,7 @@ void bd_hud_status(vector pos, vector mySize)
                {
                        mypos = pos;
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               GetPlayerName(e.minigame_playerslot-1),
+                               entcs_GetName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
 
                        mypos_y += player_fontsize_y;
@@ -1143,4 +1143,4 @@ int bd_client_event(entity minigame, string event, ...)
        return false;
 }
 
-#endif
\ No newline at end of file
+#endif
index a7ba05068ac85e929d607a43e7d0028c4385edac..9b9d570855b490d8ac01d737cfb2114329656fe7 100644 (file)
@@ -302,7 +302,7 @@ void c4_hud_board(vector pos, vector mySize)
                FOREACH_MINIGAME_ENTITY(e)
                        if ( e.classname == "minigame_player" &&
                                        e.team == (active_minigame.minigame_flags & C4_TURN_TEAM) )
-                               playername = GetPlayerName(e.minigame_playerslot-1);
+                               playername = entcs_GetName(e.minigame_playerslot-1);
 
                vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
                vector win_sz;
@@ -352,7 +352,7 @@ void c4_hud_status(vector pos, vector mySize)
                        if ( e.team == 2 )
                                mypos_y  += player_fontsize_y + ts_y;
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               GetPlayerName(e.minigame_playerslot-1),
+                               entcs_GetName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
 
                        mypos_y += player_fontsize_y;
index 93c88f6570486a6f85290a508d186ab20c2c8532..e4e0dc6380d9aec56a1b05601a8f5d733fe1b9c5 100644 (file)
@@ -477,7 +477,7 @@ void nmm_hud_board(vector pos, vector mySize)
                FOREACH_MINIGAME_ENTITY(e)
                        if ( e.classname == "minigame_player" &&
                                        e.team == (active_minigame.minigame_flags & NMM_TURN_TEAM) )
-                               playername = GetPlayerName(e.minigame_playerslot-1);
+                               playername = entcs_GetName(e.minigame_playerslot-1);
 
                vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
                vector win_sz;
@@ -531,7 +531,7 @@ void nmm_hud_status(vector pos, vector mySize)
                        if ( e.team == 2 )
                                mypos_y  += player_fontsize_y + ts_y;
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               GetPlayerName(e.minigame_playerslot-1),
+                               entcs_GetName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
                }
                else if ( e.classname == "minigame_board_piece" )
index 540f7ecf2f1d506b30a28e98f045c3783f9c4e0e..359003fffc8e676a051d972ead0bc304e3cad08f 100644 (file)
@@ -566,7 +566,7 @@ void pong_hud_status(vector pos, vector mySize)
                        drawfill(mypos, ts, pong_team_to_color(e.team), 0.25, DRAWFLAG_ADDITIVE);
 
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               (e.minigame_playerslot ? GetPlayerName(e.minigame_playerslot-1) : _("AI")),
+                               (e.minigame_playerslot ? entcs_GetName(e.minigame_playerslot-1) : _("AI")),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
 
                        drawstring(mypos+eY*player_fontsize_y,ftos(e.pong_score),'48 48 0',
index 3ef2124dcac1b72aa7a27a84e6a21bcea136c115..a66a839677d9ceed95f9e62bdeaea3d72ddf5c34 100644 (file)
@@ -354,7 +354,7 @@ void pp_hud_board(vector pos, vector mySize)
                FOREACH_MINIGAME_ENTITY(e)
                        if ( e.classname == "minigame_player" &&
                                        e.team == (active_minigame.minigame_flags & PP_TURN_TEAM) )
-                               playername = GetPlayerName(e.minigame_playerslot-1);
+                               playername = entcs_GetName(e.minigame_playerslot-1);
 
                vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
                vector win_sz;
@@ -412,7 +412,7 @@ void pp_hud_status(vector pos, vector mySize)
                        if ( e.team == 2 )
                                mypos_y  += player_fontsize_y + ts_y;
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               GetPlayerName(e.minigame_playerslot-1),
+                               entcs_GetName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
 
                        mypos_y += player_fontsize_y;
index 54be75cd46f51ba2c62756d99ec8716cb6764fd0..4eb0009b9db2ae5383906e7772270a85cc1258bf 100644 (file)
@@ -464,7 +464,7 @@ void ps_hud_status(vector pos, vector mySize)
                {
                        mypos = pos;
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               GetPlayerName(e.minigame_playerslot-1),
+                               entcs_GetName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
 
                        mypos_y += player_fontsize_y;
index cbb13420fb1573ad76e31e2b7eb6a1057e0fa51c..371df34d38d7c26a6c159160dfe403ce5fef6a81 100644 (file)
@@ -703,7 +703,7 @@ void snake_hud_status(vector pos, vector mySize)
                        if ( e.team > 1 )
                                mypos_y  += player_fontsize_y + (ts_y * (e.team - 1));
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               GetPlayerName(e.minigame_playerslot-1),
+                               entcs_GetName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
 
                        vector tile_color = snake_teamcolor(e.team);
@@ -850,4 +850,4 @@ int snake_client_event(entity minigame, string event, ...)
        return false;
 }
 
-#endif
\ No newline at end of file
+#endif
index c3c76376c169cd8b19ab22c715b50c3f47401582..cd9565abd54ce2bf401b9459f33afa4ad4a25dd3 100644 (file)
@@ -295,7 +295,7 @@ void ttt_hud_status(vector pos, vector mySize)
                        if ( e.team == 2 )
                                mypos_y  += player_fontsize_y + ts_y;
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               (e.minigame_playerslot ? GetPlayerName(e.minigame_playerslot-1) : _("AI")),
+                               (e.minigame_playerslot ? entcs_GetName(e.minigame_playerslot-1) : _("AI")),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
 
                        mypos_y += player_fontsize_y;
index 45fc349275768074459f11407fd5ccc94269b27f..e949e3a0d4969ac49d1c0d78c32e420390c8fe4d 100644 (file)
@@ -346,7 +346,7 @@ void Monster_Sound(.string samplefield, float sound_delay, float delaytoo, float
        if(delaytoo)
        if(time < self.msound_delay)
                return; // too early
-       GlobalSound_string(self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
+       GlobalSound_string(self, self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
 
        self.msound_delay = time + sound_delay;
 }
index 6cf3969e6fb168cfcb5c5f10c6e4e861387561db..f6b52dae0784e60fc08b8ddbcc20111d179ba136 100644 (file)
@@ -45,11 +45,11 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
        if(applygravity)
        {
                this.move_didgravity = 1;
-               grav = dt * (PHYS_ENTGRAVITY(this) ? PHYS_ENTGRAVITY(this) : 1) * PHYS_GRAVITY;
+               grav = dt * (PHYS_ENTGRAVITY(this) ? PHYS_ENTGRAVITY(this) : 1) * PHYS_GRAVITY(this);
 
                if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(this.move_flags & FL_ONGROUND))
                {
-                       if(GRAVITY_UNAFFECTED_BY_TICRATE)
+                       if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
                                this.move_velocity_z -= grav * 0.5;
                        else
                                this.move_velocity_z -= grav;
@@ -64,9 +64,8 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                        break;
 
                push = this.move_velocity * time_left;
-               vector prev_origin = this.move_origin;
                _Movetype_PushEntity(this, push, true);
-               if(trace_startsolid && this.move_origin != prev_origin)
+               if(trace_startsolid)
                {
                        // we got teleported by a touch function
                        // let's abort the move
@@ -88,9 +87,9 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                float my_trace_fraction = trace_fraction;
                vector my_trace_plane_normal = trace_plane_normal;
 
-               if(trace_plane_normal_z)
+               if(trace_plane_normal.z)
                {
-                       if(trace_plane_normal_z > 0.7)
+                       if(trace_plane_normal.z > 0.7)
                        {
                                // floor
                                blocked |= 1;
@@ -112,13 +111,13 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                        vector steppush = '0 0 1' * stepheight;
 
                        _Movetype_PushEntity(this, steppush, true);
-                       if(trace_startsolid && this.move_origin != org)
+                       if(trace_startsolid)
                        {
                                blocked |= 8;
                                break;
                        }
                        _Movetype_PushEntity(this, push, true);
-                       if(trace_startsolid && this.move_origin != org)
+                       if(trace_startsolid)
                        {
                                blocked |= 8;
                                break;
@@ -126,7 +125,7 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
                        float trace2_fraction = trace_fraction;
                        steppush = '0 0 1' * (org_z - this.move_origin_z);
                        _Movetype_PushEntity(this, steppush, true);
-                       if(trace_startsolid && this.move_origin != org)
+                       if(trace_startsolid)
                        {
                                blocked |= 8;
                                break;
@@ -234,7 +233,7 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnorma
        {
                if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(this.move_flags & FL_ONGROUND))
                {
-                       if(GRAVITY_UNAFFECTED_BY_TICRATE)
+                       if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
                                this.move_velocity_z -= grav * 0.5f;
                }
        }
@@ -248,38 +247,38 @@ void _Movetype_CheckVelocity(entity this)  // SV_CheckVelocity
        // this.move_velocity = '0 0 0';
 }
 
-bool _Movetype_CheckWater(entity ent)  // SV_CheckWater
+bool _Movetype_CheckWater(entity this)  // SV_CheckWater
 {
-       vector point = ent.move_origin;
-       point.z += (ent.mins.z + 1);
+       vector point = this.move_origin;
+       point.z += this.mins.z + 1;
 
        int nativecontents = pointcontents(point);
-       if(ent.move_watertype && ent.move_watertype != nativecontents)
+       if(this.move_watertype && this.move_watertype != nativecontents)
        {
-               // dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", ent.move_watertype, nativecontents);
-               if(ent.contentstransition)
-                       ent.contentstransition(ent.move_watertype, nativecontents);
+               // dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", this.move_watertype, nativecontents);
+               if(this.contentstransition)
+                       this.contentstransition(this.move_watertype, nativecontents);
        }
 
-       ent.move_waterlevel = 0;
-       ent.move_watertype = CONTENT_EMPTY;
+       this.move_waterlevel = WATERLEVEL_NONE;
+       this.move_watertype = CONTENT_EMPTY;
 
        int supercontents = Mod_Q1BSP_SuperContentsFromNativeContents(nativecontents);
        if(supercontents & DPCONTENTS_LIQUIDSMASK)
        {
-               ent.move_watertype = nativecontents;
-               ent.move_waterlevel = 1;
-               point.y = (ent.origin.y + ((ent.mins.z + ent.maxs.y) * 0.5));
+               this.move_watertype = nativecontents;
+               this.move_waterlevel = WATERLEVEL_WETFEET;
+               point.z = this.move_origin.z + (this.mins.z + this.maxs.z) * 0.5;
                if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
                {
-                       ent.move_waterlevel = 2;
-                       point.y = ent.origin.y + ent.view_ofs.y;
+                       this.move_waterlevel = WATERLEVEL_SWIMMING;
+                       point.z = this.move_origin.z + this.view_ofs.z;
                        if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
-                               ent.move_waterlevel = 3;
+                               this.move_waterlevel = WATERLEVEL_SUBMERGED;
                }
        }
 
-       return ent.move_waterlevel > 1;
+       return this.move_waterlevel > 1;
 }
 
 void _Movetype_CheckWaterTransition(entity ent)  // SV_CheckWaterTransition
@@ -344,6 +343,7 @@ void _Movetype_LinkEdict_TouchAreaGrid(entity this)  // SV_LinkEdict_TouchAreaGr
 
        for (entity e = findradius(0.5 * (this.absmin + this.absmax), 0.5 * vlen(this.absmax - this.absmin)); e; e = e.chain)
        {
+               if(e.move_nomonsters != MOVE_NOMONSTERS && e.move_nomonsters != MOVE_WORLDONLY)
                if(e.move_touch && boxesoverlap(e.absmin, e.absmax, this.absmin, this.absmax))
                {
                        other = this;
@@ -353,7 +353,7 @@ void _Movetype_LinkEdict_TouchAreaGrid(entity this)  // SV_LinkEdict_TouchAreaGr
                        trace_fraction = 1;
                        trace_inwater = false;
                        trace_inopen = true;
-                       trace_endpos = e.origin;
+                       trace_endpos = e.move_origin;
                        trace_plane_normal = '0 0 1';
                        trace_plane_dist = 0;
                        trace_ent = this;
@@ -414,7 +414,7 @@ bool _Movetype_TestEntityPosition(entity this, vector ofs)  // SV_TestEntityPosi
 
        int cont = this.dphitcontentsmask;
        this.dphitcontentsmask = DPCONTENTS_SOLID;
-       tracebox(this.move_origin, this.mins, this.maxs, this.move_origin, MOVE_NOMONSTERS, this);
+       tracebox(this.move_origin, this.mins, this.maxs, this.move_origin, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
        this.dphitcontentsmask = cont;
 
        if(trace_startsolid)
@@ -441,11 +441,11 @@ bool _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
                if(!_Movetype_TestEntityPosition(this, '0 0 -1' * i)) goto success;
                if(!_Movetype_TestEntityPosition(this, '0 0 1' * i)) goto success;
        }
-       LOG_TRACEF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
+       LOG_DEBUG("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
                num_for_edict(this), this.classname, vtos(this.move_origin));
        return false;
        : success;
-       LOG_TRACEF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
+       LOG_DEBUG("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
                num_for_edict(this), this.classname, vtos(this.move_origin));
        _Movetype_LinkEdict(this, true);
        return true;
@@ -470,6 +470,8 @@ void _Movetype_PushEntityTrace(entity this, vector push)
                type = max(0, this.move_nomonsters);
        else if(this.move_movetype == MOVETYPE_FLYMISSILE)
                type = MOVE_MISSILE;
+       else if(this.move_movetype == MOVETYPE_FLY_WORLDONLY)
+               type = MOVE_WORLDONLY;
        else if(this.solid == SOLID_TRIGGER || this.solid == SOLID_NOT)
                type = MOVE_NOMONSTERS;
        else
@@ -583,8 +585,50 @@ void _Movetype_Physics_Frame(entity this, float movedt)
                case MOVETYPE_BOUNCEMISSILE:
                case MOVETYPE_FLYMISSILE:
                case MOVETYPE_FLY:
+               case MOVETYPE_FLY_WORLDONLY:
                        _Movetype_Physics_Toss(this, movedt);
                        break;
+               case MOVETYPE_PHYSICS:
+                       break;
+       }
+}
+
+void _Movetype_Physics_ClientFrame(entity this, float movedt)
+{
+       this.move_didgravity = -1;
+       switch (this.move_movetype)
+       {
+               case MOVETYPE_PUSH:
+               case MOVETYPE_FAKEPUSH:
+                       _Movetype_Physics_Pusher(this, movedt);
+                       break;
+               case MOVETYPE_NONE:
+                       break;
+               case MOVETYPE_FOLLOW:
+                       _Movetype_Physics_Follow(this);
+                       break;
+               case MOVETYPE_NOCLIP:
+                       _Movetype_CheckWater(this);
+                       this.move_origin = this.move_origin + TICRATE * this.move_velocity;
+                       this.move_angles = this.move_angles + TICRATE * this.move_avelocity;
+                       _Movetype_LinkEdict(this, false);
+                       break;
+               case MOVETYPE_STEP:
+                       _Movetype_Physics_Step(this, movedt);
+                       break;
+               case MOVETYPE_WALK:
+               case MOVETYPE_FLY:
+               case MOVETYPE_FLY_WORLDONLY:
+                       _Movetype_Physics_Walk(this, movedt);
+                       break;
+               case MOVETYPE_TOSS:
+               case MOVETYPE_BOUNCE:
+               case MOVETYPE_BOUNCEMISSILE:
+               case MOVETYPE_FLYMISSILE:
+                       _Movetype_Physics_Toss(this, movedt);
+                       break;
+               case MOVETYPE_PHYSICS:
+                       break;
        }
 }
 
@@ -641,10 +685,10 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
 
                if(this.move_didgravity > 0)
                {
-                       this.velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+                       this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
                            * dt
                            * (this.gravity ? this.gravity : 1)
-                           * PHYS_GRAVITY;
+                           * PHYS_GRAVITY(this);
                }
 
                this.angles = this.move_angles + dt * this.avelocity;
@@ -660,8 +704,8 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
                                setorigin(this, trace_endpos);
                }
 
-               if(this.move_didgravity > 0 && GRAVITY_UNAFFECTED_BY_TICRATE)
-                       this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY;
+               if(this.move_didgravity > 0 && GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
+                       this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
        }
        else
        {
index 2102247d5523f68fa577da36bc4dea20e12c834a..7578ae2fa446faae30fe97a44e84522c2a58e67d 100644 (file)
 // should match sv_gameplayfix_fixedcheckwatertransition
 float autocvar_cl_gameplayfix_fixedcheckwatertransition = 1;
 
-#ifdef SVQC
-.int stat_gameplayfix_upvelocityclearsonground;
-
-#define GRAVITY_UNAFFECTED_BY_TICRATE autocvar_sv_gameplayfix_gravityunaffectedbyticrate
-#define UPWARD_VELOCITY_CLEARS_ONGROUND autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag
-
-#define TICRATE sys_frametime
-#elif defined(CSQC)
-#define GRAVITY_UNAFFECTED_BY_TICRATE (getstati(STAT_MOVEFLAGS) & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
-#define UPWARD_VELOCITY_CLEARS_ONGROUND getstati(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND)
-
-#define TICRATE ticrate
-#endif
-
 .entity move_groundentity;  // FIXME add move_groundnetworkentity?
 .float move_suspendedinair;
 .float move_didgravity;
@@ -83,6 +69,7 @@ const int MOVETYPE_FLYMISSILE       = 9;
 const int MOVETYPE_BOUNCE           = 10;
 const int MOVETYPE_BOUNCEMISSILE    = 11;  // Like bounce but doesn't lose speed on bouncing
 const int MOVETYPE_FOLLOW           = 12;
+const int MOVETYPE_PHYSICS          = 32;
 const int MOVETYPE_FLY_WORLDONLY    = 33;
 
 const int FL_ITEM                   = 256;
@@ -91,13 +78,13 @@ const int FL_ONGROUND                               = 512;
 
 const int MOVETYPE_FAKEPUSH         = 13;
 
-const float MOVEFLAG_Q2AIRACCELERATE            = 1;
-const float MOVEFLAG_NOGRAVITYONGROUND          = 2;
-const float MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = 4;
+const int MOVEFLAG_VALID = BIT(23);
+const int MOVEFLAG_Q2AIRACCELERATE = BIT(0);
+const int MOVEFLAG_NOGRAVITYONGROUND = BIT(1);
+const int MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE = BIT(2);
 
 #ifdef CSQC
-// TODO: figure out server's version of this
-#define moveflags (getstati(STAT_MOVEFLAGS))
+#define moveflags STAT(MOVEFLAGS)
 #endif
 
 #endif
index 06302090f2189cd8e7143186072096fb4cd5e427..3029c9a9df8b4385ffd3c541de993648dd73b787 100644 (file)
@@ -4,7 +4,7 @@ void _Movetype_Physics_Toss(entity this, float dt)  // SV_Physics_Toss
 {
        if (this.move_flags & FL_ONGROUND)
        {
-               if (this.move_velocity.z >= 1 / 32)
+               if (this.move_velocity.z >= 1 / 32 && UPWARD_VELOCITY_CLEARS_ONGROUND)
                {
                        this.move_flags &= ~FL_ONGROUND;
                }
@@ -26,10 +26,10 @@ void _Movetype_Physics_Toss(entity this, float dt)  // SV_Physics_Toss
        if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
        {
                this.move_didgravity = 1;
-               this.move_velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+               this.move_velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
                    * dt
                    * (this.gravity ? this.gravity : 1)
-                   * PHYS_GRAVITY;
+                   * PHYS_GRAVITY(this);
        }
 
        this.move_angles = this.move_angles + this.move_avelocity * dt;
@@ -64,7 +64,7 @@ void _Movetype_Physics_Toss(entity this, float dt)  // SV_Physics_Toss
                {
                        float bouncefac = this.move_bounce_factor;     if (!bouncefac)  bouncefac = 0.5;
                        float bouncestop = this.move_bounce_stopspeed; if (!bouncestop) bouncestop = 60 / 800;
-                       bouncestop *= (this.gravity ? this.gravity : 1) * PHYS_GRAVITY;
+                       bouncestop *= (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
 
                        this.move_velocity = _Movetype_ClipVelocity(this.move_velocity, trace_plane_normal, 1 + bouncefac);
 
@@ -108,8 +108,8 @@ void _Movetype_Physics_Toss(entity this, float dt)  // SV_Physics_Toss
                        break;
        }
 
-       if (GRAVITY_UNAFFECTED_BY_TICRATE && this.move_didgravity > 0 && !(this.move_flags & FL_ONGROUND))
-               this.move_velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY;
+       if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE && this.move_didgravity > 0 && !(this.move_flags & FL_ONGROUND))
+               this.move_velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
 
        _Movetype_CheckWaterTransition(this);
 }
index 23d6e01a8f0ce7e2790222785c05bd377ee5ab84..7fab2787ea01ceb85baacc4c5f4680074b9f9044 100644 (file)
@@ -89,11 +89,10 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
 
                // move up
                vector upmove = '0 0 1' * PHYS_STEPHEIGHT;
-               vector prev_origin = this.move_origin;
                _Movetype_PushEntity(this, upmove, true);
                if(wasfreed(this))
                        return;
-               if(trace_startsolid && this.move_origin != prev_origin)
+               if(trace_startsolid)
                {
                        // we got teleported when upstepping... must abort the move
                        return;
@@ -145,12 +144,11 @@ void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
 
        // move down
        vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT + start_velocity.z * dt);
-       vector prev_origin = this.move_origin;
        _Movetype_PushEntity(this, downmove, true);
        if(wasfreed(this))
                return;
 
-       if(trace_startsolid && this.move_origin != prev_origin)
+       if(trace_startsolid)
        {
                // we got teleported when downstepping... must abort the move
                return;
index 7cfc297896ab7fd9e6ca91789e5e481455a21afa..54b7b662413e28aff63f1c6795aef7ea11237063 100644 (file)
@@ -157,6 +157,50 @@ ENDCLASS(Mutator)
 REGISTRY(Mutators, BITS(7))
 #define Mutators_from(i) _Mutators_from(i, NULL)
 Mutator loaded_mutators[Mutators_MAX];
+bool Mutator_Add(Mutator mut);
+void Mutator_Remove(Mutator mut);
+bool mutator_log = false;
+
+#ifndef MENUQC
+REGISTER_NET_LINKED(Mutator)
+
+#ifdef SVQC
+bool Mutator_SendEntity(entity this, entity to, int sf)
+{
+    int chan = MSG_ENTITY;
+    WriteHeader(chan, Mutator);
+    WriteString(chan, this.registered_id);
+    return true;
+}
+#endif
+
+#ifdef CSQC
+void NET_Mutator_Remove()
+{
+    SELFPARAM();
+    string s = this.netname;
+    WITH(bool, mutator_log, true, LAMBDA(
+        FOREACH(Mutators, it.registered_id == s, LAMBDA(Mutator_Remove(it)));
+    ));
+}
+NET_HANDLE(Mutator, bool isNew)
+{
+    string s = this.netname = ReadString();
+    return = true;
+    if (isNew)
+    {
+        make_pure(this);
+        this.entremove = NET_Mutator_Remove;
+        int added = 0;
+        WITH(bool, mutator_log, true, LAMBDA(
+            FOREACH(Mutators, it.registered_id == s, LAMBDA(Mutator_Add(it); ++added));
+        ));
+        if (added > 1) LOG_WARNINGF("Added more than one mutator for %s\n", s);
+    }
+}
+#endif
+
+#endif
 
 bool Mutator_Add(Mutator mut)
 {
@@ -175,6 +219,10 @@ bool Mutator_Add(Mutator mut)
     mutatorfunc_t func = mut.mutatorfunc;
     if (!func(MUTATOR_ADDING)) {
         // good
+        if (mutator_log) LOG_TRACEF("Mutator: added %s\n", mut.m_name);
+#ifdef SVQC
+        Net_LinkEntity(mut, false, 0, Mutator_SendEntity);
+#endif
         return true;
     }
     backtrace("WARNING: when adding mutator: adding failed, rolling back\n");
@@ -201,6 +249,10 @@ void Mutator_Remove(Mutator mut)
         // baaaaad
         error("Mutator_Remove: removing mutator failed");
     }
+    if (mutator_log) LOG_TRACEF("Mutator: removed %s\n", mut.m_name);
+#ifdef SVQC
+    Net_UnlinkEntity(mut);
+#endif
 }
 
 #define REGISTER_MUTATOR(id, dependence) \
index ed57753bdece4b34514d6bf241518690967d5853..5cb5b4745a5705657053ca6c6ce940072e0c68d6 100644 (file)
@@ -90,4 +90,14 @@ MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
 float pm_maxspeed_mod;
 MUTATOR_HOOKABLE(PM_Physics, EV_PM_Physics);
 
+/** called when a weapon model is about to be set, allows custom paths etc. */
+#define EV_WeaponModel(i, o) \
+    /**/ i(string, weapon_model) \
+    /**/ i(string, weapon_model_output) \
+    /**/ o(string, weapon_model_output) \
+    /**/
+string weapon_model;
+string weapon_model_output;
+MUTATOR_HOOKABLE(WeaponModel, EV_WeaponModel);
+
 #endif
index db22d314115f510c7a58369af9c2c8b1d9678754..76ecff8be1bac913082922b65dc297de6d4ba10b 100644 (file)
@@ -44,7 +44,7 @@ CLASS(Buff, Pickup)
 ENDCLASS(Buff)
 
 #ifdef SVQC
-       .int buffs;
+       // .int buffs = _STAT(BUFFS);
        void buff_Init(entity ent);
        void buff_Init_Compat(entity ent, entity replacement);
        #define BUFF_SPAWNFUNC(e, b, t) spawnfunc(item_buff_##e) { \
index f4f6df73aa806ee3c3a0b372118d5ae0e0405115..1c9e3a2177b9f3c07f5822392e0232d4d88ba6e7 100644 (file)
@@ -76,16 +76,13 @@ const vector BUFF_MAX = ('16 16 20');
 #include "../../../triggers/target/music.qh"
 #include "../../../gamemodes/all.qh"
 
-.float buff_time;
+.float buff_time = _STAT(BUFF_TIME);
 void buffs_DelayedInit();
 
 REGISTER_MUTATOR(buffs, cvar("g_buffs"))
 {
        MUTATOR_ONADD
        {
-               addstat(STAT_BUFFS, AS_INT, buffs);
-               addstat(STAT_BUFF_TIME, AS_FLOAT, buff_time);
-
                InitializeEntity(world, buffs_DelayedInit, INITPRIO_FINDTARGET);
        }
 }
index 5f24f627e7a5879b06dc1a98cecffec9d1b256ca..be00977148ef05ad8bdf2a55ff534454c8305e65 100644 (file)
@@ -24,9 +24,9 @@ MUTATOR_HOOKFUNCTION(buffs_flight, IsFlying)
 REGISTER_MUTATOR(cl_buffs, true);
 MUTATOR_HOOKFUNCTION(cl_buffs, HUD_Powerups_add)
 {
-    int allBuffs = getstati(STAT_BUFFS, 0, 24);
+    int allBuffs = STAT(BUFFS);
     FOREACH(Buffs, it.m_itemid & allBuffs, LAMBDA(
-               addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, getstatf(STAT_BUFF_TIME) - time, 99), 60);
+               addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
        ));
 }
 MUTATOR_HOOKFUNCTION(cl_buffs, WP_Format)
index 9eb16b040d7d3d64a0fcc1aadae974b7ae6f3d08..194341383dc2d5afd8c8cdf014c907c4bc3cc418 100644 (file)
@@ -7,14 +7,12 @@
 
 #if defined(SVQC)
 void bugrigs_SetVars();
-void bugrigs_AddStats();
 
 REGISTER_MUTATOR(bugrigs, cvar("g_bugrigs"))
 {
        MUTATOR_ONADD
        {
                bugrigs_SetVars();
-               bugrigs_AddStats();
        }
        return false;
 }
@@ -23,73 +21,23 @@ REGISTER_MUTATOR(bugrigs, true);
 #endif
 
 
-#ifdef CSQC
-
-#define PHYS_BUGRIGS                                           getstati(STAT_BUGRIGS)
-#define PHYS_BUGRIGS_ANGLE_SMOOTHING           getstati(STAT_BUGRIGS_ANGLE_SMOOTHING)
-#define PHYS_BUGRIGS_PLANAR_MOVEMENT           getstati(STAT_BUGRIGS_PLANAR_MOVEMENT)
-#define PHYS_BUGRIGS_REVERSE_SPEEDING          getstati(STAT_BUGRIGS_REVERSE_SPEEDING)
-#define PHYS_BUGRIGS_FRICTION_FLOOR            getstatf(STAT_BUGRIGS_FRICTION_FLOOR)
-#define PHYS_BUGRIGS_AIR_STEERING                      getstati(STAT_BUGRIGS_AIR_STEERING)
-#define PHYS_BUGRIGS_FRICTION_BRAKE            getstatf(STAT_BUGRIGS_FRICTION_BRAKE)
-#define PHYS_BUGRIGS_ACCEL                                     getstatf(STAT_BUGRIGS_ACCEL)
-#define PHYS_BUGRIGS_SPEED_REF                                 getstatf(STAT_BUGRIGS_SPEED_REF)
-#define PHYS_BUGRIGS_SPEED_POW                                 getstatf(STAT_BUGRIGS_SPEED_POW)
-#define PHYS_BUGRIGS_STEER                                     getstatf(STAT_BUGRIGS_STEER)
-#define PHYS_BUGRIGS_FRICTION_AIR                      getstatf(STAT_BUGRIGS_FRICTION_AIR)
-#define PHYS_BUGRIGS_CAR_JUMPING                       getstatf(STAT_BUGRIGS_CAR_JUMPING)
-#define PHYS_BUGRIGS_REVERSE_SPINNING          getstatf(STAT_BUGRIGS_REVERSE_SPINNING)
-#define PHYS_BUGRIGS_REVERSE_STOPPING          getstatf(STAT_BUGRIGS_REVERSE_STOPPING)
-
-#elif defined(SVQC)
-
-bool g_bugrigs;
-bool g_bugrigs_planar_movement;
-bool g_bugrigs_planar_movement_car_jumping;
-float g_bugrigs_reverse_spinning;
-float g_bugrigs_reverse_speeding;
-float g_bugrigs_reverse_stopping;
-float g_bugrigs_air_steering;
-float g_bugrigs_angle_smoothing;
-float g_bugrigs_friction_floor;
-float g_bugrigs_friction_brake;
-float g_bugrigs_friction_air;
-float g_bugrigs_accel;
-float g_bugrigs_speed_ref;
-float g_bugrigs_speed_pow;
-float g_bugrigs_steer;
-
-#define PHYS_BUGRIGS                                           g_bugrigs
-#define PHYS_BUGRIGS_ANGLE_SMOOTHING           g_bugrigs_angle_smoothing
-#define PHYS_BUGRIGS_PLANAR_MOVEMENT           g_bugrigs_planar_movement
-#define PHYS_BUGRIGS_REVERSE_SPEEDING          g_bugrigs_reverse_speeding
-#define PHYS_BUGRIGS_FRICTION_FLOOR                    g_bugrigs_friction_floor
-#define PHYS_BUGRIGS_AIR_STEERING                      g_bugrigs_air_steering
-#define PHYS_BUGRIGS_FRICTION_BRAKE                    g_bugrigs_friction_brake
-#define PHYS_BUGRIGS_ACCEL                                     g_bugrigs_accel
-#define PHYS_BUGRIGS_SPEED_REF                         g_bugrigs_speed_ref
-#define PHYS_BUGRIGS_SPEED_POW                         g_bugrigs_speed_pow
-#define PHYS_BUGRIGS_STEER                                     g_bugrigs_steer
-#define PHYS_BUGRIGS_FRICTION_AIR                      g_bugrigs_friction_air
-#define PHYS_BUGRIGS_CAR_JUMPING                       g_bugrigs_planar_movement_car_jumping
-#define PHYS_BUGRIGS_REVERSE_SPINNING          g_bugrigs_reverse_spinning
-#define PHYS_BUGRIGS_REVERSE_STOPPING          g_bugrigs_reverse_stopping
-
-.float stat_bugrigs;
-.float stat_bugrigs_angle_smoothing;
-.float stat_bugrigs_planar_movement;
-.float stat_bugrigs_reverse_speeding;
-.float stat_bugrigs_friction_floor;
-.float stat_bugrigs_air_steering;
-.float stat_bugrigs_friction_brake;
-.float stat_bugrigs_accel;
-.float stat_bugrigs_speed_ref;
-.float stat_bugrigs_speed_pow;
-.float stat_bugrigs_steer;
-.float stat_bugrigs_friction_air;
-.float stat_bugrigs_car_jumping;
-.float stat_bugrigs_reverse_spinning;
-.float stat_bugrigs_reverse_stopping;
+#define PHYS_BUGRIGS(s)                        STAT(BUGRIGS, s)
+#define PHYS_BUGRIGS_ACCEL(s)                  STAT(BUGRIGS_ACCEL, s)
+#define PHYS_BUGRIGS_AIR_STEERING(s)           STAT(BUGRIGS_AIR_STEERING, s)
+#define PHYS_BUGRIGS_ANGLE_SMOOTHING(s)        STAT(BUGRIGS_ANGLE_SMOOTHING, s)
+#define PHYS_BUGRIGS_CAR_JUMPING(s)            STAT(BUGRIGS_CAR_JUMPING, s)
+#define PHYS_BUGRIGS_FRICTION_AIR(s)           STAT(BUGRIGS_FRICTION_AIR, s)
+#define PHYS_BUGRIGS_FRICTION_BRAKE(s)         STAT(BUGRIGS_FRICTION_BRAKE, s)
+#define PHYS_BUGRIGS_FRICTION_FLOOR(s)         STAT(BUGRIGS_FRICTION_FLOOR, s)
+#define PHYS_BUGRIGS_PLANAR_MOVEMENT(s)        STAT(BUGRIGS_PLANAR_MOVEMENT, s)
+#define PHYS_BUGRIGS_REVERSE_SPEEDING(s)       STAT(BUGRIGS_REVERSE_SPEEDING, s)
+#define PHYS_BUGRIGS_REVERSE_SPINNING(s)       STAT(BUGRIGS_REVERSE_SPINNING, s)
+#define PHYS_BUGRIGS_REVERSE_STOPPING(s)       STAT(BUGRIGS_REVERSE_STOPPING, s)
+#define PHYS_BUGRIGS_SPEED_POW(s)              STAT(BUGRIGS_SPEED_POW, s)
+#define PHYS_BUGRIGS_SPEED_REF(s)              STAT(BUGRIGS_SPEED_REF, s)
+#define PHYS_BUGRIGS_STEER(s)                  STAT(BUGRIGS_STEER, s)
+
+#if defined(SVQC)
 
 void bugrigs_SetVars()
 {
@@ -110,44 +58,6 @@ void bugrigs_SetVars()
        g_bugrigs_steer = cvar("g_bugrigs_steer");
 }
 
-void bugrigs_UpdateStats(entity this)
-{
-       this.stat_bugrigs = PHYS_BUGRIGS;
-       this.stat_bugrigs_angle_smoothing = PHYS_BUGRIGS_ANGLE_SMOOTHING;
-       this.stat_bugrigs_planar_movement = PHYS_BUGRIGS_PLANAR_MOVEMENT;
-       this.stat_bugrigs_reverse_speeding = PHYS_BUGRIGS_REVERSE_SPEEDING;
-       this.stat_bugrigs_friction_floor = PHYS_BUGRIGS_FRICTION_FLOOR;
-       this.stat_bugrigs_air_steering = PHYS_BUGRIGS_AIR_STEERING;
-       this.stat_bugrigs_friction_brake = PHYS_BUGRIGS_FRICTION_BRAKE;
-       this.stat_bugrigs_accel = PHYS_BUGRIGS_ACCEL;
-       this.stat_bugrigs_speed_ref = PHYS_BUGRIGS_SPEED_REF;
-       this.stat_bugrigs_speed_pow = PHYS_BUGRIGS_SPEED_POW;
-       this.stat_bugrigs_steer = PHYS_BUGRIGS_STEER;
-       this.stat_bugrigs_friction_air = PHYS_BUGRIGS_FRICTION_AIR;
-       this.stat_bugrigs_car_jumping = PHYS_BUGRIGS_CAR_JUMPING;
-       this.stat_bugrigs_reverse_spinning = PHYS_BUGRIGS_REVERSE_SPINNING;
-       this.stat_bugrigs_reverse_stopping = PHYS_BUGRIGS_REVERSE_STOPPING;
-}
-
-void bugrigs_AddStats()
-{
-       addstat(STAT_BUGRIGS, AS_INT, stat_bugrigs);
-       addstat(STAT_BUGRIGS_ANGLE_SMOOTHING, AS_INT, stat_bugrigs_angle_smoothing);
-       addstat(STAT_BUGRIGS_PLANAR_MOVEMENT, AS_INT, stat_bugrigs_planar_movement);
-       addstat(STAT_BUGRIGS_REVERSE_SPEEDING, AS_INT, stat_bugrigs_reverse_speeding);
-       addstat(STAT_BUGRIGS_FRICTION_FLOOR, AS_FLOAT, stat_bugrigs_friction_floor);
-       addstat(STAT_BUGRIGS_AIR_STEERING, AS_INT, stat_bugrigs_air_steering);
-       addstat(STAT_BUGRIGS_FRICTION_BRAKE, AS_FLOAT, stat_bugrigs_friction_brake);
-       addstat(STAT_BUGRIGS_ACCEL, AS_FLOAT, stat_bugrigs_accel);
-       addstat(STAT_BUGRIGS_SPEED_REF, AS_FLOAT, stat_bugrigs_speed_ref);
-       addstat(STAT_BUGRIGS_SPEED_POW, AS_FLOAT, stat_bugrigs_speed_pow);
-       addstat(STAT_BUGRIGS_STEER, AS_FLOAT, stat_bugrigs_steer);
-       addstat(STAT_BUGRIGS_FRICTION_AIR, AS_FLOAT, stat_bugrigs_friction_air);
-       addstat(STAT_BUGRIGS_CAR_JUMPING, AS_FLOAT, stat_bugrigs_car_jumping);
-       addstat(STAT_BUGRIGS_REVERSE_SPINNING, AS_FLOAT, stat_bugrigs_reverse_spinning);
-       addstat(STAT_BUGRIGS_REVERSE_STOPPING, AS_FLOAT, stat_bugrigs_reverse_stopping);
-}
-
 #endif
 
 void RaceCarPhysics(entity this)
@@ -161,7 +71,7 @@ void RaceCarPhysics(entity this)
        float accel = bound(-1, this.movement.x / PHYS_MAXSPEED(this), 1);
        float steer = bound(-1, this.movement.y / PHYS_MAXSPEED(this), 1);
 
-       if (PHYS_BUGRIGS_REVERSE_SPEEDING)
+       if (PHYS_BUGRIGS_REVERSE_SPEEDING(this))
        {
                if (accel < 0)
                {
@@ -178,56 +88,56 @@ void RaceCarPhysics(entity this)
        this.angles_z = 0;
        makevectors(this.angles); // new forward direction!
 
-       if (IS_ONGROUND(this) || PHYS_BUGRIGS_AIR_STEERING)
+       if (IS_ONGROUND(this) || PHYS_BUGRIGS_AIR_STEERING(this))
        {
                float myspeed = this.velocity * v_forward;
                float upspeed = this.velocity * v_up;
 
                // responsiveness factor for steering and acceleration
-               float f = 1 / (1 + pow(max(-myspeed, myspeed) / PHYS_BUGRIGS_SPEED_REF, PHYS_BUGRIGS_SPEED_POW));
-               //MAXIMA: f(v) := 1 / (1 + (v / PHYS_BUGRIGS_SPEED_REF) ^ PHYS_BUGRIGS_SPEED_POW);
+               float f = 1 / (1 + pow(max(-myspeed, myspeed) / PHYS_BUGRIGS_SPEED_REF(this), PHYS_BUGRIGS_SPEED_POW(this)));
+               //MAXIMA: f(v) := 1 / (1 + (v / PHYS_BUGRIGS_SPEED_REF(this)) ^ PHYS_BUGRIGS_SPEED_POW(this));
 
                float steerfactor;
-               if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPINNING)
-                       steerfactor = -myspeed * PHYS_BUGRIGS_STEER;
+               if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPINNING(this))
+                       steerfactor = -myspeed * PHYS_BUGRIGS_STEER(this);
                else
-                       steerfactor = -myspeed * f * PHYS_BUGRIGS_STEER;
+                       steerfactor = -myspeed * f * PHYS_BUGRIGS_STEER(this);
 
                float accelfactor;
-               if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPEEDING)
-                       accelfactor = PHYS_BUGRIGS_ACCEL;
+               if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+                       accelfactor = PHYS_BUGRIGS_ACCEL(this);
                else
-                       accelfactor = f * PHYS_BUGRIGS_ACCEL;
-               //MAXIMA: accel(v) := f(v) * PHYS_BUGRIGS_ACCEL;
+                       accelfactor = f * PHYS_BUGRIGS_ACCEL(this);
+               //MAXIMA: accel(v) := f(v) * PHYS_BUGRIGS_ACCEL(this);
 
                if (accel < 0)
                {
                        if (myspeed > 0)
                        {
-                               myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR - PHYS_BUGRIGS_FRICTION_BRAKE * accel));
+                               myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) - PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
                        }
                        else
                        {
-                               if (!PHYS_BUGRIGS_REVERSE_SPEEDING)
-                                       myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR);
+                               if (!PHYS_BUGRIGS_REVERSE_SPEEDING(this))
+                                       myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
                        }
                }
                else
                {
                        if (myspeed >= 0)
                        {
-                               myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR);
+                               myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
                        }
                        else
                        {
-                               if (PHYS_BUGRIGS_REVERSE_STOPPING)
+                               if (PHYS_BUGRIGS_REVERSE_STOPPING(this))
                                        myspeed = 0;
                                else
-                                       myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR + PHYS_BUGRIGS_FRICTION_BRAKE * accel));
+                                       myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) + PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
                        }
                }
                // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
-               //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR;
+               //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR(this);
 
                this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
                makevectors(this.angles); // new forward direction!
@@ -241,7 +151,7 @@ void RaceCarPhysics(entity this)
                float myspeed = vlen(this.velocity);
 
                // responsiveness factor for steering and acceleration
-               float f = 1 / (1 + pow(max(0, myspeed / PHYS_BUGRIGS_SPEED_REF), PHYS_BUGRIGS_SPEED_POW));
+               float f = 1 / (1 + pow(max(0, myspeed / PHYS_BUGRIGS_SPEED_REF(this)), PHYS_BUGRIGS_SPEED_POW(this)));
                float steerfactor = -myspeed * f;
                this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
 
@@ -249,20 +159,20 @@ void RaceCarPhysics(entity this)
                makevectors(this.angles); // new forward direction!
        }
 
-       rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR * PHYS_INPUT_TIMELENGTH);
-       //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR;
+       rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR(this) * PHYS_INPUT_TIMELENGTH);
+       //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR(this);
        //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
        //MAXIMA: solve(total_acceleration(v) = 0, v);
 
-       if (PHYS_BUGRIGS_PLANAR_MOVEMENT)
+       if (PHYS_BUGRIGS_PLANAR_MOVEMENT(this))
        {
                vector rigvel_xy, neworigin, up;
                float mt;
 
-               rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
+               rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
                rigvel_xy = vec2(rigvel);
 
-               if (PHYS_BUGRIGS_CAR_JUMPING)
+               if (PHYS_BUGRIGS_CAR_JUMPING(this))
                        mt = MOVE_NORMAL;
                else
                        mt = MOVE_NOMONSTERS;
@@ -308,7 +218,7 @@ void RaceCarPhysics(entity this)
        }
        else
        {
-               rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
+               rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
                this.velocity = rigvel;
                this.movetype = MOVETYPE_FLY;
        }
@@ -341,7 +251,7 @@ void RaceCarPhysics(entity this)
        // smooth the angles
        vector vf1, vu1, smoothangles;
        makevectors(this.angles);
-       float f = bound(0, PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_ANGLE_SMOOTHING, 1);
+       float f = bound(0, PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_ANGLE_SMOOTHING(this), 1);
        if (f == 0)
                f = 1;
        vf1 = v_forward * f;
@@ -361,7 +271,7 @@ void RaceCarPhysics(entity this)
 #endif
 MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
 {
-       if(!PHYS_BUGRIGS || !IS_PLAYER(self)) { return false; }
+       if(!PHYS_BUGRIGS(self) || !IS_PLAYER(self)) { return false; }
 
 #ifdef SVQC
        self.angles = self.bugrigs_prevangles;
@@ -373,11 +283,9 @@ MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
 
 MUTATOR_HOOKFUNCTION(bugrigs, PlayerPhysics)
 {
-       if(!PHYS_BUGRIGS) { return false; }
+       if(!PHYS_BUGRIGS(self)) { return false; }
 #ifdef SVQC
        self.bugrigs_prevangles = self.angles;
-
-       bugrigs_UpdateStats(self);
 #endif
        return false;
 }
index 327f78b1d53c98b5c4eebeadb6098809eaab6238..3521ca77f7c838c05efa5094a9b4215f2f087c13 100644 (file)
@@ -1,49 +1,30 @@
 #ifdef IMPLEMENTATION
 
+#define PHYS_DODGING                                           STAT(DODGING, this)
+#define PHYS_DODGING_DELAY                                     STAT(DODGING_DELAY, this)
+#define PHYS_DODGING_DISTANCE_THRESHOLD        STAT(DODGING_DISTANCE_THRESHOLD, this)
+#define PHYS_DODGING_FROZEN_NODOUBLETAP                STAT(DODGING_FROZEN_NO_DOUBLETAP, this)
+#define PHYS_DODGING_HEIGHT_THRESHOLD          STAT(DODGING_HEIGHT_THRESHOLD, this)
+#define PHYS_DODGING_HORIZ_SPEED                       STAT(DODGING_HORIZ_SPEED, this)
+#define PHYS_DODGING_HORIZ_SPEED_FROZEN        STAT(DODGING_HORIZ_SPEED_FROZEN, this)
+#define PHYS_DODGING_RAMP_TIME                                 STAT(DODGING_RAMP_TIME, this)
+#define PHYS_DODGING_UP_SPEED                          STAT(DODGING_UP_SPEED, this)
+#define PHYS_DODGING_WALL                                      STAT(DODGING_WALL, this)
+#define PHYS_DODGING_PRESSED_KEYS(s)           (s).pressedkeys
+
 #ifdef CSQC
        #define PHYS_DODGING_FRAMETIME                          (1 / (frametime <= 0 ? 60 : frametime))
-       #define PHYS_DODGING                                            getstati(STAT_DODGING)
-       #define PHYS_DODGING_DELAY                                      getstatf(STAT_DODGING_DELAY)
-       #define PHYS_DODGING_TIMEOUT(s)                         getstatf(STAT_DODGING_TIMEOUT)
-       #define PHYS_DODGING_HORIZ_SPEED_FROZEN         getstatf(STAT_DODGING_HORIZ_SPEED_FROZEN)
-       #define PHYS_DODGING_FROZEN_NODOUBLETAP         getstati(STAT_DODGING_FROZEN_NO_DOUBLETAP)
-       #define PHYS_DODGING_HORIZ_SPEED                        getstatf(STAT_DODGING_HORIZ_SPEED)
-       #define PHYS_DODGING_PRESSED_KEYS(s)            s.pressedkeys
-       #define PHYS_DODGING_HEIGHT_THRESHOLD           getstatf(STAT_DODGING_HEIGHT_THRESHOLD)
-       #define PHYS_DODGING_DISTANCE_THRESHOLD         getstatf(STAT_DODGING_DISTANCE_THRESHOLD)
-       #define PHYS_DODGING_RAMP_TIME                          getstatf(STAT_DODGING_RAMP_TIME)
-       #define PHYS_DODGING_UP_SPEED                           getstatf(STAT_DODGING_UP_SPEED)
-       #define PHYS_DODGING_WALL                                       getstatf(STAT_DODGING_WALL)
+       #define PHYS_DODGING_TIMEOUT(s)                         STAT(DODGING_TIMEOUT)
 #elif defined(SVQC)
        #define PHYS_DODGING_FRAMETIME                          sys_frametime
-       #define PHYS_DODGING                                            g_dodging
-       #define PHYS_DODGING_DELAY                                      autocvar_sv_dodging_delay
        #define PHYS_DODGING_TIMEOUT(s)                         s.cvar_cl_dodging_timeout
-       #define PHYS_DODGING_HORIZ_SPEED_FROZEN         autocvar_sv_dodging_horiz_speed_frozen
-       #define PHYS_DODGING_FROZEN_NODOUBLETAP         autocvar_sv_dodging_frozen_doubletap
-       #define PHYS_DODGING_HORIZ_SPEED                        autocvar_sv_dodging_horiz_speed
-       #define PHYS_DODGING_PRESSED_KEYS(s)            s.pressedkeys
-       #define PHYS_DODGING_HEIGHT_THRESHOLD           autocvar_sv_dodging_height_threshold
-       #define PHYS_DODGING_DISTANCE_THRESHOLD         autocvar_sv_dodging_wall_distance_threshold
-       #define PHYS_DODGING_RAMP_TIME                          autocvar_sv_dodging_ramp_time
-       #define PHYS_DODGING_UP_SPEED                           autocvar_sv_dodging_up_speed
-       #define PHYS_DODGING_WALL                                       autocvar_sv_dodging_wall_dodging
-
-       float autocvar_sv_dodging_delay;
-    float autocvar_sv_dodging_height_threshold;
-    float autocvar_sv_dodging_horiz_speed;
-    float autocvar_sv_dodging_horiz_speed_frozen;
-    float autocvar_sv_dodging_ramp_time;
-    bool autocvar_sv_dodging_sound;
-    float autocvar_sv_dodging_up_speed;
-    float autocvar_sv_dodging_wall_distance_threshold;
-    bool autocvar_sv_dodging_wall_dodging;
-    bool autocvar_sv_dodging_frozen_doubletap;
+
+
 #endif
 
 #ifdef SVQC
 
-float g_dodging;
+bool autocvar_sv_dodging_sound;
 
 // set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
 .float dodging_action;
@@ -54,19 +35,7 @@ float g_dodging;
 #include "../../../animdecide.qh"
 #include "../../../physics.qh"
 
-.float cvar_cl_dodging_timeout;
-
-.float stat_dodging;
-.float stat_dodging_delay;
-.float stat_dodging_horiz_speed_frozen;
-.float stat_dodging_frozen_nodoubletap;
-.float stat_dodging_frozen;
-.float stat_dodging_horiz_speed;
-.float stat_dodging_height_threshold;
-.float stat_dodging_distance_threshold;
-.float stat_dodging_ramp_time;
-.float stat_dodging_up_speed;
-.float stat_dodging_wall;
+.float cvar_cl_dodging_timeout = _STAT(DODGING_TIMEOUT);
 
 REGISTER_MUTATOR(dodging, cvar("g_dodging"))
 {
@@ -74,18 +43,6 @@ REGISTER_MUTATOR(dodging, cvar("g_dodging"))
        MUTATOR_ONADD
        {
                g_dodging = cvar("g_dodging");
-               addstat(STAT_DODGING, AS_INT, stat_dodging);
-               addstat(STAT_DODGING_DELAY, AS_FLOAT, stat_dodging_delay);
-               addstat(STAT_DODGING_TIMEOUT, AS_FLOAT, cvar_cl_dodging_timeout); // we stat this, so it is updated on the client when updated on server (otherwise, chaos)
-               addstat(STAT_DODGING_FROZEN_NO_DOUBLETAP, AS_INT, stat_dodging_frozen_nodoubletap);
-               addstat(STAT_DODGING_HORIZ_SPEED_FROZEN, AS_FLOAT, stat_dodging_horiz_speed_frozen);
-               addstat(STAT_DODGING_FROZEN, AS_INT, stat_dodging_frozen);
-               addstat(STAT_DODGING_HORIZ_SPEED, AS_FLOAT, stat_dodging_horiz_speed);
-               addstat(STAT_DODGING_HEIGHT_THRESHOLD, AS_FLOAT, stat_dodging_height_threshold);
-               addstat(STAT_DODGING_DISTANCE_THRESHOLD, AS_FLOAT, stat_dodging_distance_threshold);
-               addstat(STAT_DODGING_RAMP_TIME, AS_FLOAT, stat_dodging_ramp_time);
-               addstat(STAT_DODGING_UP_SPEED, AS_FLOAT, stat_dodging_up_speed);
-               addstat(STAT_DODGING_WALL, AS_FLOAT, stat_dodging_wall);
        }
 
        // this just turns off the cvar.
@@ -130,22 +87,6 @@ REGISTER_MUTATOR(dodging, true);
 .int pressedkeys;
 #endif
 
-void dodging_UpdateStats(entity this)
-{
-#ifdef SVQC
-       this.stat_dodging = PHYS_DODGING;
-       this.stat_dodging_delay = PHYS_DODGING_DELAY;
-       this.stat_dodging_horiz_speed_frozen = PHYS_DODGING_HORIZ_SPEED_FROZEN;
-       this.stat_dodging_frozen = PHYS_DODGING_FROZEN;
-       this.stat_dodging_frozen_nodoubletap = PHYS_DODGING_FROZEN_NODOUBLETAP;
-       this.stat_dodging_height_threshold = PHYS_DODGING_HEIGHT_THRESHOLD;
-       this.stat_dodging_distance_threshold = PHYS_DODGING_DISTANCE_THRESHOLD;
-       this.stat_dodging_ramp_time = PHYS_DODGING_RAMP_TIME;
-       this.stat_dodging_up_speed = PHYS_DODGING_UP_SPEED;
-       this.stat_dodging_wall = PHYS_DODGING_WALL;
-#endif
-}
-
 // returns 1 if the player is close to a wall
 bool check_close_to_wall(entity this, float threshold)
 {
@@ -235,8 +176,6 @@ void PM_dodging(entity this)
        if (!PHYS_DODGING)
                return;
 
-       dodging_UpdateStats(this);
-
     if (PHYS_DEAD(this))
         return;
 
@@ -287,7 +226,7 @@ void PM_dodging(entity this)
 
 #ifdef SVQC
                if (autocvar_sv_dodging_sound)
-                       PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+                       PlayerSound(this, playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
 
                animdecide_setaction(this, ANIMACTION_JUMP, true);
 #endif
index a2bd9ca0c54c295106958a96e8c9d7d4ee8a1ea8..a7aaa780f9df472200d6de1360e6a1367b484403 100644 (file)
@@ -4,51 +4,18 @@
 #endif
 #include "../../../physics.qh"
 
-
-#if defined(SVQC)
-void doublejump_AddStats();
-
-REGISTER_MUTATOR(doublejump, true)
-{
-       MUTATOR_ONADD
-       {
-               doublejump_AddStats();
-       }
-       return false;
-}
+#ifdef SVQC
+REGISTER_MUTATOR(doublejump, autocvar_sv_doublejump);
 #elif defined(CSQC)
 REGISTER_MUTATOR(doublejump, true);
 #endif
 
-
-#ifdef CSQC
-
-#define PHYS_DOUBLEJUMP                                                getstati(STAT_DOUBLEJUMP)
-
-#elif defined(SVQC)
-
-bool autocvar_sv_doublejump;
-
-#define PHYS_DOUBLEJUMP                                                autocvar_sv_doublejump
-
-.int stat_doublejump;
-
-void doublejump_UpdateStats(entity this)
-{
-       this.stat_doublejump = PHYS_DOUBLEJUMP;
-}
-
-void doublejump_AddStats()
-{
-       addstat(STAT_DOUBLEJUMP, AS_INT, stat_doublejump);
-}
-
-#endif
+#define PHYS_DOUBLEJUMP(s)                     STAT(DOUBLEJUMP, s)
 
 
 MUTATOR_HOOKFUNCTION(doublejump, PlayerJump)
 {
-       if (PHYS_DOUBLEJUMP)
+       if (PHYS_DOUBLEJUMP(self))
        {
                tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
                if (trace_fraction < 1 && trace_plane_normal_z > 0.7)
@@ -64,27 +31,4 @@ MUTATOR_HOOKFUNCTION(doublejump, PlayerJump)
        return false;
 }
 
-MUTATOR_HOOKFUNCTION(doublejump, PlayerPhysics)
-{
-#ifdef SVQC
-       doublejump_UpdateStats(self);
-#endif
-       return false;
-}
-
-#ifdef SVQC
-
-MUTATOR_HOOKFUNCTION(doublejump, BuildMutatorsString)
-{
-       ret_string = strcat(ret_string, ":doublejump");
-       return false;
-}
-
-MUTATOR_HOOKFUNCTION(doublejump, BuildMutatorsPrettyString)
-{
-       ret_string = strcat(ret_string, ", Double jump");
-       return false;
-}
-
-#endif
 #endif
index 6472c83ae87c4d56639fc66fb8eb085070649a5c..7a8b2921880046ee077639b023b69f75bee50322 100644 (file)
@@ -6,88 +6,30 @@
 
 
 #if defined(SVQC)
-void multijump_AddStats();
-
-REGISTER_MUTATOR(multijump, cvar("g_multijump"))
-{
-       MUTATOR_ONADD
-       {
-               multijump_AddStats();
-       }
-       return false;
-}
+REGISTER_MUTATOR(multijump, cvar("g_multijump"));
 #elif defined(CSQC)
 REGISTER_MUTATOR(multijump, true);
 #endif
 
-.int multijump_count;
+#define PHYS_MULTIJUMP                                 STAT(MULTIJUMP, self)
+#define PHYS_MULTIJUMP_SPEED           STAT(MULTIJUMP_SPEED, self)
+#define PHYS_MULTIJUMP_ADD                     STAT(MULTIJUMP_ADD, self)
+#define PHYS_MULTIJUMP_MAXSPEED        STAT(MULTIJUMP_MAXSPEED, self)
+#define PHYS_MULTIJUMP_DODGING                 STAT(MULTIJUMP_DODGING, self)
+#define PHYS_MULTIJUMP_COUNT(s)        STAT(MULTIJUMP_COUNT, s)
+
 .bool multijump_ready;
 
 #ifdef CSQC
+bool autocvar_cl_multijump = false;
 
-bool autocvar_cl_multijump = true;
-
-#define PHYS_MULTIJUMP                                 getstati(STAT_MULTIJUMP)
-#define PHYS_MULTIJUMP_SPEED           getstatf(STAT_MULTIJUMP_SPEED)
-#define PHYS_MULTIJUMP_ADD                     getstati(STAT_MULTIJUMP_ADD)
-#define PHYS_MULTIJUMP_MAXSPEED        getstatf(STAT_MULTIJUMP_MAXSPEED)
-#define PHYS_MULTIJUMP_DODGING                 getstati(STAT_MULTIJUMP_DODGING)
-#define PHYS_MULTIJUMP_COUNT(s)        getstati(STAT_MULTIJUMP_COUNT)
-#define PHYS_MULTIJUMP_CLIENT(s)       autocvar_cl_multijump
-
+       #define PHYS_MULTIJUMP_CLIENT(s)        autocvar_cl_multijump
 #elif defined(SVQC)
-
 .bool cvar_cl_multijump;
 
-int autocvar_g_multijump;
-float autocvar_g_multijump_add;
-float autocvar_g_multijump_speed;
-float autocvar_g_multijump_maxspeed;
-float autocvar_g_multijump_dodging = 1;
-
-#define PHYS_MULTIJUMP                                 autocvar_g_multijump
-#define PHYS_MULTIJUMP_SPEED           autocvar_g_multijump_speed
-#define PHYS_MULTIJUMP_ADD                     autocvar_g_multijump_add
-#define PHYS_MULTIJUMP_MAXSPEED        autocvar_g_multijump_maxspeed
-#define PHYS_MULTIJUMP_DODGING                 autocvar_g_multijump_dodging
-#define PHYS_MULTIJUMP_COUNT(s)        (s).multijump_count
-#define PHYS_MULTIJUMP_CLIENT(s)       (s).cvar_cl_multijump
-
-.float stat_multijump;
-.float stat_multijump_speed;
-.float stat_multijump_add;
-.float stat_multijump_maxspeed;
-.float stat_multijump_dodging;
-
-void multijump_UpdateStats(entity this)
-{
-       this.stat_multijump = PHYS_MULTIJUMP;
-       this.stat_multijump_speed = PHYS_MULTIJUMP_SPEED;
-       this.stat_multijump_add = PHYS_MULTIJUMP_ADD;
-       this.stat_multijump_maxspeed = PHYS_MULTIJUMP_MAXSPEED;
-       this.stat_multijump_dodging = PHYS_MULTIJUMP_DODGING;
-}
-
-void multijump_AddStats()
-{
-       addstat(STAT_MULTIJUMP, AS_INT, stat_multijump);
-       addstat(STAT_MULTIJUMP_SPEED, AS_FLOAT, stat_multijump_speed);
-       addstat(STAT_MULTIJUMP_ADD, AS_INT, stat_multijump_add);
-       addstat(STAT_MULTIJUMP_MAXSPEED, AS_FLOAT, stat_multijump_maxspeed);
-       addstat(STAT_MULTIJUMP_DODGING, AS_INT, stat_multijump_dodging);
-       addstat(STAT_MULTIJUMP_COUNT, AS_INT, multijump_count);
-}
-
+       #define PHYS_MULTIJUMP_CLIENT(s)        (s).cvar_cl_multijump
 #endif
 
-void PM_multijump(entity this)
-{
-       if(!PHYS_MULTIJUMP) { return; }
-
-       if(IS_ONGROUND(this))
-               this.multijump_count = 0;
-}
-
 bool PM_multijump_checkjump(entity this)
 {
        if(!PHYS_MULTIJUMP) { return false; }
@@ -157,12 +99,13 @@ bool PM_multijump_checkjump(entity this)
 
 MUTATOR_HOOKFUNCTION(multijump, PlayerPhysics)
 {
-#ifdef SVQC
-       multijump_UpdateStats(self);
-#elif defined(CSQC)
+#ifdef CSQC
        self.multijump_count = PHYS_MULTIJUMP_COUNT(self);
 #endif
-       PM_multijump(self);
+       if(!PHYS_MULTIJUMP) { return; }
+
+       if(IS_ONGROUND(self))
+               self.multijump_count = 0;
        return false;
 }
 
index 459d95020308e36159cc271b45c2d20572d744eb..c1ab9774dacc7d8a9cfb93d7cd9739a7a60163dc 100644 (file)
@@ -31,9 +31,9 @@ entity Nade_TrailEffect(int proj, int nade_team)
 REGISTER_MUTATOR(cl_nades, true);
 MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay)
 {
-       if (getstatf(STAT_HEALING_ORB) <= time) return false;
+       if (STAT(HEALING_ORB) <= time) return false;
        MUTATOR_ARGV(0, vector) = NADE_TYPE_HEAL.m_color;
-       MUTATOR_ARGV(0, float) = getstatf(STAT_HEALING_ORB_ALPHA);
+       MUTATOR_ARGV(0, float) = STAT(HEALING_ORB_ALPHA);
        return true;
 }
 MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
@@ -82,9 +82,9 @@ bool Projectile_isnade(int p)
 }
 void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time)
 {
-       float bonusNades    = getstatf(STAT_NADE_BONUS);
-       float bonusProgress = getstatf(STAT_NADE_BONUS_SCORE);
-       float bonusType     = getstati(STAT_NADE_BONUS_TYPE);
+       float bonusNades    = STAT(NADE_BONUS);
+       float bonusProgress = STAT(NADE_BONUS_SCORE);
+       float bonusType     = STAT(NADE_BONUS_TYPE);
        Nade def = Nades_from(bonusType);
        vector nadeColor    = def.m_color;
        string nadeIcon     = def.m_icon;
@@ -124,20 +124,7 @@ void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expan
 #include "../../../monsters/sv_monsters.qh"
 #include "../../../../server/g_subs.qh"
 
-REGISTER_MUTATOR(nades, cvar("g_nades"))
-{
-       MUTATOR_ONADD
-       {
-               addstat(STAT_NADE_TIMER, AS_FLOAT, nade_timer);
-               addstat(STAT_NADE_BONUS, AS_FLOAT, bonus_nades);
-               addstat(STAT_NADE_BONUS_TYPE, AS_INT, nade_type);
-               addstat(STAT_NADE_BONUS_SCORE, AS_FLOAT, bonus_nade_score);
-               addstat(STAT_HEALING_ORB, AS_FLOAT, stat_healing_orb);
-               addstat(STAT_HEALING_ORB_ALPHA, AS_FLOAT, stat_healing_orb_alpha);
-       }
-
-       return false;
-}
+REGISTER_MUTATOR(nades, cvar("g_nades"));
 
 .float nade_time_primed;
 
index 2e4829354ac67b8081cf5af0dd7b6f1bb9361237..312cf4ae2dd606e1013890c552db826f261b1b1c 100644 (file)
@@ -63,19 +63,19 @@ Nade Nade_FromProjectile(int proj)
 
 .entity nade;
 .entity fake_nade;
-.float nade_timer;
+.float nade_timer = _STAT(NADE_TIMER);
 .float nade_refire;
-.float bonus_nades;
+.float bonus_nades = _STAT(NADE_BONUS);
 .float nade_special_time;
-.float bonus_nade_score;
-.float nade_type;
+.float bonus_nade_score = _STAT(NADE_BONUS_SCORE);
+.int nade_type = _STAT(NADE_BONUS_TYPE);
 .string pokenade_type;
 .entity nade_damage_target;
 .float cvar_cl_nade_type;
 .string cvar_cl_pokenade_type;
 .float toss_time;
-.float stat_healing_orb;
-.float stat_healing_orb_alpha;
+.float stat_healing_orb = _STAT(HEALING_ORB);
+.float stat_healing_orb_alpha = _STAT(HEALING_ORB_ALPHA);
 .float nade_show_particles;
 
 bool healer_send(entity this, entity to, int sf);
index 5235e58e62df2c0faac3de32a2550cb51c1c11cc..2a0df8c642cce3b1157525e477675a64a833cb2e 100644 (file)
@@ -79,14 +79,14 @@ REGISTER_MUTATOR(nt, cvar("g_new_toys") && !cvar("g_instagib") && !cvar("g_overk
                // mark the guns as ok to use by e.g. impulse 99
                for(int i = WEP_FIRST; i <= WEP_LAST; ++i)
                        if(nt_IsNewToy(i))
-                               get_weaponinfo(i).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
+                               Weapons_from(i).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
        }
 
        MUTATOR_ONROLLBACK_OR_REMOVE
        {
                for(int i = WEP_FIRST; i <= WEP_LAST; ++i)
                        if(nt_IsNewToy(i))
-                               get_weaponinfo(i).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
+                               Weapons_from(i).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
        }
 
        MUTATOR_ONREMOVE
@@ -168,7 +168,7 @@ MUTATOR_HOOKFUNCTION(nt, SetStartItems)
 
        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
        {
-               entity e = get_weaponinfo(i);
+               entity e = Weapons_from(i);
                if(!e.weapon)
                        continue;
 
@@ -177,7 +177,7 @@ MUTATOR_HOOKFUNCTION(nt, SetStartItems)
                for (j = 0; j < n; ++j)
                        for (k = WEP_FIRST; k <= WEP_LAST; ++k)
                        {
-                               Weapon w = get_weaponinfo(k);
+                               Weapon w = Weapons_from(k);
                                if (w.netname == argv(j))
                                {
                                        WepSet seti = e.m_wepset;
index 73b08bce8be60c72eec2e5d062df2d218c832e16..a07ad44cac4a25d6d96959810a5324c4f9d5b077 100644 (file)
@@ -45,7 +45,7 @@ REGISTER_MUTATOR(nix, cvar("g_nix") && !cvar("g_instagib") && !cvar("g_overkill"
 
                for (int i = WEP_FIRST; i <= WEP_LAST; ++i)
                        if (NIX_CanChooseWeapon(i)) {
-                               Weapon w = get_weaponinfo(i);
+                               Weapon w = Weapons_from(i);
                                w.wr_init(w);
                        }
        }
@@ -78,7 +78,7 @@ REGISTER_MUTATOR(nix, cvar("g_nix") && !cvar("g_instagib") && !cvar("g_overkill"
 
 bool NIX_CanChooseWeapon(int wpn)
 {
-       entity e = get_weaponinfo(wpn);
+       entity e = Weapons_from(wpn);
        if(!e.weapon) // skip dummies
                return false;
        if(g_weaponarena)
@@ -124,12 +124,12 @@ void NIX_GiveCurrentWeapon()
                        nix_nextchange = time; // start the first round now!
                else
                        nix_nextchange = time + autocvar_g_balance_nix_roundtime;
-               // Weapon w = get_weaponinfo(nix_weapon);
+               // Weapon w = Weapons_from(nix_weapon);
                // w.wr_init(w); // forget it, too slow
        }
 
        // get weapon info
-       entity e = get_weaponinfo(nix_weapon);
+       entity e = Weapons_from(nix_weapon);
 
        if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
        {
index 7f2341fb0e53a7b2f8e7741ee9b1d5c6b47b526d..8341f7c71d4230faa24cf86286e3f29a742f7c7b 100644 (file)
@@ -61,8 +61,7 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
                return;
        }
 
-       Weapon w = get_weaponinfo(actor.weapon);
-       if(!w.wr_checkammo1(w))
+       if(!thiswep.wr_checkammo1(thiswep))
        if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
@@ -108,8 +107,7 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
                METHOD(HeavyMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
                {
                        if(WEP_CVAR(hmg, reload_ammo) && actor.clip_load < WEP_CVAR(hmg, ammo)) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else
                        {
                                if (fire & 1)
index a8bde27b566028cb0bab2f617caec150fb734e46..a7acff5a09e05a580d703eef7f54a8b2a7af0133 100644 (file)
@@ -4,3 +4,16 @@
 #ifdef SVQC
        #include "overkill.qc"
 #endif
+#ifdef CSQC
+       #ifdef IMPLEMENTATION
+               REGISTER_MUTATOR(ok, false)
+               {
+                       MUTATOR_ONADD {
+                               cvar_settemp("g_overkill", "1");
+                               WEP_SHOTGUN.mdl = "ok_shotgun";
+                               WEP_MACHINEGUN.mdl = "ok_mg";
+                               WEP_VORTEX.mdl = "ok_sniper";
+                       }
+               }
+       #endif
+#endif
index 151e094c9eb72ce16b0cabfb86c0182f1c32d75b..05b6ddde34ae3bb9560259da179eca784ebe8d82 100644 (file)
@@ -14,8 +14,8 @@ float autocvar_g_overkill_ammo_charge_limit;
 
 .float ok_notice_time;
 .float ammo_charge[Weapons_MAX];
-.float ok_use_ammocharge;
-.float ok_ammo_charge;
+.float ok_use_ammocharge = _STAT(OK_AMMO_CHARGE);
+.float ok_ammo_charge = _STAT(OK_AMMO_CHARGEPOOL);
 
 .float ok_pauseregen_finished;
 
@@ -63,7 +63,7 @@ void ok_DecreaseCharge(entity ent, int wep)
 {
        if(!ent.ok_use_ammocharge) return;
 
-       entity wepent = get_weaponinfo(wep);
+       entity wepent = Weapons_from(wep);
 
        if(wepent.weapon == 0)
                return; // dummy
@@ -73,7 +73,7 @@ void ok_DecreaseCharge(entity ent, int wep)
 
 void ok_IncreaseCharge(entity ent, int wep)
 {
-       entity wepent = get_weaponinfo(wep);
+       entity wepent = Weapons_from(wep);
 
        if(wepent.weapon == 0)
                return; // dummy
@@ -87,7 +87,7 @@ float ok_CheckWeaponCharge(entity ent, int wep)
 {
        if(!ent.ok_use_ammocharge) return true;
 
-       entity wepent = get_weaponinfo(wep);
+       entity wepent = Weapons_from(wep);
 
        if(wepent.weapon == 0)
                return 0; // dummy
@@ -229,7 +229,7 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
                        self.ok_notice_time = time + 2;
                        play2(self, SND(DRYFIRE));
                }
-               Weapon wpn = get_weaponinfo(self.weapon);
+               Weapon wpn = Weapons_from(self.weapon);
                .entity weaponentity = weaponentities[0]; // TODO: unhardcode
                if(self.(weaponentity).state != WS_CLEAR)
                        w_ready(wpn, self, weaponentity, (self.BUTTON_ATCK ? 1 : 0) | (self.BUTTON_ATCK2 ? 2 : 0));
@@ -372,9 +372,6 @@ void ok_Initialize()
 
        precache_all_playermodels("models/ok_player/*.dpm");
 
-       addstat(STAT_OK_AMMO_CHARGE, AS_FLOAT, ok_use_ammocharge);
-       addstat(STAT_OK_AMMO_CHARGEPOOL, AS_FLOAT, ok_ammo_charge);
-
        WEP_RPC.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
        WEP_HMG.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
 
index 05aa9239d718f0514e8208aa149e4b666f24000e..94f1bd10cf5ba38bf4242ec4a0564e083377a0f1 100644 (file)
@@ -156,8 +156,7 @@ void W_RocketPropelledChainsaw_Attack (Weapon thiswep)
                METHOD(RocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
                {
                        if(WEP_CVAR(rpc, reload_ammo) && actor.clip_load < WEP_CVAR(rpc, ammo)) {
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else
                        {
                                if (fire & 1)
index a806b2958a94de70d73cc9f7f82baaf1c1254763..99c1321c1aaa37062f84830272978a5efdaea0fc 100644 (file)
@@ -4,7 +4,7 @@ REGISTER_MUTATOR(pinata, cvar("g_pinata") && !cvar("g_instagib") && !cvar("g_ove
 MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
 {SELFPARAM();
        for(int j = WEP_FIRST; j <= WEP_LAST; ++j)
-       if(self.weapons & WepSet_FromWeapon(j))
+       if(self.weapons & WepSet_FromWeapon(Weapons_from(j)))
        if(self.switchweapon != j)
        if(W_IsWeaponThrowable(j))
                W_ThrowNewWeapon(self, j, false, self.origin + (self.mins + self.maxs) * 0.5, randomvec() * 175 + '0 0 325');
index cd78b4082f835d3b07c6deea99481c176c70df64..42d8d6b7f54a13b42b5cec33b5f519a9fc052502 100644 (file)
@@ -7,7 +7,7 @@ float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
 int autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
 bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
 
-REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate") && teamplay);
+REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate"));
 
 .entity msnt_lookat;
 
@@ -54,6 +54,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, Spawn_Score)
 
 MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn)
 {SELFPARAM();
+       if(!teamplay) { return false; }
        // Note: when entering this, fixangle is already set.
        if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && self.cvar_cl_spawn_near_teammate))
        {
@@ -85,7 +86,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn)
                                                else
                                                        fixedmakevectors(team_mate.angles);
 
-                                               for(pc = 0; pc != 5; ++pc) // test 5 diffrent spots close to mate
+                                               for(pc = 0; pc < 5; ++pc) // test 5 diffrent spots close to mate
                                                {
                                                        switch(pc)
                                                        {
index a66a92993355ca8f3873a100837a06366fa1b71b..9db086a8bbc0b5acffc2e1a4ebaa0eb6ea5fa3e8 100644 (file)
@@ -221,7 +221,7 @@ void Ent_WaypointSprite()
 float spritelookupblinkvalue(string s)
 {SELFPARAM();
     if (s == WP_Weapon.netname) {
-        if (get_weaponinfo(self.wp_extra).spawnflags & WEP_FLAG_SUPERWEAPON)
+        if (Weapons_from(self.wp_extra).spawnflags & WEP_FLAG_SUPERWEAPON)
             return 2;
     }
     if (s == WP_Item.netname) return Items_from(self.wp_extra).m_waypointblink;
@@ -231,7 +231,7 @@ float spritelookupblinkvalue(string s)
 
 vector spritelookupcolor(entity this, string s, vector def)
 {
-    if (s == WP_Weapon.netname  || s == RADARICON_Weapon.netname) return get_weaponinfo(this.wp_extra).wpcolor;
+    if (s == WP_Weapon.netname  || s == RADARICON_Weapon.netname) return Weapons_from(this.wp_extra).wpcolor;
     if (s == WP_Item.netname    || s == RADARICON_Item.netname) return Items_from(this.wp_extra).m_color;
     if (MUTATOR_CALLHOOK(WP_Format, this, s))
     {
@@ -243,7 +243,7 @@ vector spritelookupcolor(entity this, string s, vector def)
 string spritelookuptext(string s)
 {SELFPARAM();
     if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
-    if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).m_name;
+    if (s == WP_Weapon.netname) return Weapons_from(self.wp_extra).m_name;
     if (s == WP_Item.netname) return Items_from(self.wp_extra).m_waypoint;
     if (s == WP_Monster.netname) return get_monsterinfo(self.wp_extra).monster_name;
     if (MUTATOR_CALLHOOK(WP_Format, this, s))
@@ -469,7 +469,7 @@ void Draw_WaypointSprite(entity this)
 
     InterpolateOrigin_Do(self);
 
-    float t = GetPlayerColor(player_localnum) + 1;
+    float t = entcs_GetTeam(player_localnum) + 1;
 
     string spriteimage = "";
 
index 285321a9a504cb27d532d0a97fdc1c9d39640a39..f7551e253a5341be8df131b048529c4a3f011f05 100644 (file)
@@ -30,142 +30,37 @@ float Physics_ClientOption(entity this, string option)
        return cvar(strcat("sv_", option));
 }
 
-void Physics_AddStats()
-{
-       // static view offset and hitbox vectors
-       // networked for all you bandwidth pigs out there
-       addstat(STAT_PL_VIEW_OFS1, AS_FLOAT, stat_pl_view_ofs_x);
-       addstat(STAT_PL_VIEW_OFS2, AS_FLOAT, stat_pl_view_ofs_y);
-       addstat(STAT_PL_VIEW_OFS3, AS_FLOAT, stat_pl_view_ofs_z);
-       addstat(STAT_PL_CROUCH_VIEW_OFS1, AS_FLOAT, stat_pl_crouch_view_ofs_x);
-       addstat(STAT_PL_CROUCH_VIEW_OFS2, AS_FLOAT, stat_pl_crouch_view_ofs_y);
-       addstat(STAT_PL_CROUCH_VIEW_OFS3, AS_FLOAT, stat_pl_crouch_view_ofs_z);
-
-       addstat(STAT_PL_MIN1, AS_FLOAT, stat_pl_min_x);
-       addstat(STAT_PL_MIN2, AS_FLOAT, stat_pl_min_y);
-       addstat(STAT_PL_MIN3, AS_FLOAT, stat_pl_min_z);
-       addstat(STAT_PL_MAX1, AS_FLOAT, stat_pl_max_x);
-       addstat(STAT_PL_MAX2, AS_FLOAT, stat_pl_max_y);
-       addstat(STAT_PL_MAX3, AS_FLOAT, stat_pl_max_z);
-       addstat(STAT_PL_CROUCH_MIN1, AS_FLOAT, stat_pl_crouch_min_x);
-       addstat(STAT_PL_CROUCH_MIN2, AS_FLOAT, stat_pl_crouch_min_y);
-       addstat(STAT_PL_CROUCH_MIN3, AS_FLOAT, stat_pl_crouch_min_z);
-       addstat(STAT_PL_CROUCH_MAX1, AS_FLOAT, stat_pl_crouch_max_x);
-       addstat(STAT_PL_CROUCH_MAX2, AS_FLOAT, stat_pl_crouch_max_y);
-       addstat(STAT_PL_CROUCH_MAX3, AS_FLOAT, stat_pl_crouch_max_z);
-
-       // g_movementspeed hack
-       addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
-       addstat(STAT_MOVEVARS_MAXSPEED, AS_FLOAT, stat_sv_maxspeed);
-       addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw);
-       addstat(STAT_MOVEVARS_AIRSTRAFEACCEL_QW, AS_FLOAT, stat_sv_airstrafeaccel_qw);
-       addstat(STAT_MOVEVARS_HIGHSPEED, AS_FLOAT, stat_movement_highspeed);
-
-       // jet pack
-       addstat(STAT_JETPACK_ACCEL_SIDE, AS_FLOAT, stat_jetpack_accel_side);
-       addstat(STAT_JETPACK_ACCEL_UP, AS_FLOAT, stat_jetpack_accel_up);
-       addstat(STAT_JETPACK_ANTIGRAVITY, AS_FLOAT, stat_jetpack_antigravity);
-       addstat(STAT_JETPACK_FUEL, AS_FLOAT, stat_jetpack_fuel);
-       addstat(STAT_JETPACK_MAXSPEED_UP, AS_FLOAT, stat_jetpack_maxspeed_up);
-       addstat(STAT_JETPACK_MAXSPEED_SIDE, AS_FLOAT, stat_jetpack_maxspeed_side);
-
-       // hack to fix track_canjump
-       addstat(STAT_MOVEVARS_CL_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
-       addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, stat_sv_track_canjump);
-
-       // jump speed caps
-       addstat(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, AS_INT, stat_jumpspeedcap_disable_onramps);
-
-       // hacks
-       addstat(STAT_MOVEVARS_FRICTION_ONLAND, AS_FLOAT, stat_sv_friction_on_land);
-       addstat(STAT_MOVEVARS_FRICTION_SLICK, AS_FLOAT, stat_sv_friction_slick);
-       addstat(STAT_GAMEPLAYFIX_EASIERWATERJUMP, AS_INT, stat_gameplayfix_easierwaterjump);
-
-       // new properties
-       addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
-       addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
-       addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
-       addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
-       addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
-       addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
-       addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
-       addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
-       addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
-       addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
-       addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
-       addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
-       addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
-       addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
-
-       addstat(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, AS_INT, stat_gameplayfix_upvelocityclearsonground);
-}
-
 void Physics_UpdateStats(entity this, float maxspd_mod)
 {
-       // blah
-       this.stat_pl_view_ofs = PL_VIEW_OFS;
-       this.stat_pl_crouch_view_ofs = PL_CROUCH_VIEW_OFS;
-
-       this.stat_pl_min = PL_MIN;
-       this.stat_pl_max = PL_MAX;
-       this.stat_pl_crouch_min = PL_CROUCH_MIN;
-       this.stat_pl_crouch_max = PL_CROUCH_MAX;
-
-
-       this.stat_sv_airaccel_qw = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw"), maxspd_mod);
-       if(Physics_ClientOption(this, "airstrafeaccel_qw"))
-               this.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw"), maxspd_mod);
-       else
-               this.stat_sv_airstrafeaccel_qw = 0;
-       this.stat_sv_airspeedlimit_nonqw = Physics_ClientOption(this, "airspeedlimit_nonqw") * maxspd_mod;
-       this.stat_sv_maxspeed = Physics_ClientOption(this, "maxspeed") * maxspd_mod; // also slow walking
-       this.stat_movement_highspeed = PHYS_HIGHSPEED; // TODO: remove this!
-
-       this.stat_jetpack_antigravity = PHYS_JETPACK_ANTIGRAVITY;
-       this.stat_jetpack_accel_up = PHYS_JETPACK_ACCEL_UP;
-       this.stat_jetpack_accel_side = PHYS_JETPACK_ACCEL_SIDE;
-       this.stat_jetpack_maxspeed_side = PHYS_JETPACK_MAXSPEED_SIDE;
-       this.stat_jetpack_maxspeed_up = PHYS_JETPACK_MAXSPEED_UP;
-       this.stat_jetpack_fuel = PHYS_JETPACK_FUEL;
-
-       this.stat_jumpspeedcap_disable_onramps = PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS;
-
-       this.stat_sv_friction_on_land = PHYS_FRICTION_ONLAND;
-       this.stat_sv_friction_slick = PHYS_FRICTION_SLICK;
-
-       this.stat_gameplayfix_easierwaterjump = GAMEPLAYFIX_EASIERWATERJUMP;
-
+       STAT(MOVEVARS_AIRACCEL_QW, this) = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw"), maxspd_mod);
+       STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = (Physics_ClientOption(this, "airstrafeaccel_qw"))
+               ? AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw"), maxspd_mod)
+               : 0;
+       STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw") * maxspd_mod;
+       STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed") * maxspd_mod; // also slow walking
 
        // old stats
        // fix some new settings
-       this.stat_sv_airaccel_qw_stretchfactor = Physics_ClientOption(this, "airaccel_qw_stretchfactor");
-       this.stat_sv_maxairstrafespeed = Physics_ClientOption(this, "maxairstrafespeed");
-       this.stat_sv_maxairspeed = Physics_ClientOption(this, "maxairspeed");
-       this.stat_sv_airstrafeaccelerate = Physics_ClientOption(this, "airstrafeaccelerate");
-       this.stat_sv_warsowbunny_turnaccel = Physics_ClientOption(this, "warsowbunny_turnaccel");
-       this.stat_sv_airaccel_sideways_friction = Physics_ClientOption(this, "airaccel_sideways_friction");
-       this.stat_sv_aircontrol = Physics_ClientOption(this, "aircontrol");
-       this.stat_sv_aircontrol_power = Physics_ClientOption(this, "aircontrol_power");
-       this.stat_sv_aircontrol_penalty = Physics_ClientOption(this, "aircontrol_penalty");
-       this.stat_sv_warsowbunny_airforwardaccel = Physics_ClientOption(this, "warsowbunny_airforwardaccel");
-       this.stat_sv_warsowbunny_topspeed = Physics_ClientOption(this, "warsowbunny_topspeed");
-       this.stat_sv_warsowbunny_accel = Physics_ClientOption(this, "warsowbunny_accel");
-       this.stat_sv_warsowbunny_backtosideratio = Physics_ClientOption(this, "warsowbunny_backtosideratio");
-       this.stat_sv_friction = Physics_ClientOption(this, "friction");
-       this.stat_sv_accelerate = Physics_ClientOption(this, "accelerate");
-       this.stat_sv_stopspeed = Physics_ClientOption(this, "stopspeed");
-       this.stat_sv_airaccelerate = Physics_ClientOption(this, "airaccelerate");
-       this.stat_sv_airstopaccelerate = Physics_ClientOption(this, "airstopaccelerate");
-       this.stat_sv_jumpvelocity = Physics_ClientOption(this, "jumpvelocity");
-
-       this.stat_sv_track_canjump = Physics_ClientOption(this, "track_canjump");
-
-       this.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND;
+       STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, this) = Physics_ClientOption(this, "airaccel_qw_stretchfactor");
+       STAT(MOVEVARS_MAXAIRSTRAFESPEED, this) = Physics_ClientOption(this, "maxairstrafespeed");
+       STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed");
+       STAT(MOVEVARS_AIRSTRAFEACCELERATE, this) = Physics_ClientOption(this, "airstrafeaccelerate");
+       STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, this) = Physics_ClientOption(this, "warsowbunny_turnaccel");
+       STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, this) = Physics_ClientOption(this, "airaccel_sideways_friction");
+       STAT(MOVEVARS_AIRCONTROL, this) = Physics_ClientOption(this, "aircontrol");
+       STAT(MOVEVARS_AIRCONTROL_POWER, this) = Physics_ClientOption(this, "aircontrol_power");
+       STAT(MOVEVARS_AIRCONTROL_PENALTY, this) = Physics_ClientOption(this, "aircontrol_penalty");
+       STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, this) = Physics_ClientOption(this, "warsowbunny_airforwardaccel");
+       STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, this) = Physics_ClientOption(this, "warsowbunny_topspeed");
+       STAT(MOVEVARS_WARSOWBUNNY_ACCEL, this) = Physics_ClientOption(this, "warsowbunny_accel");
+       STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, this) = Physics_ClientOption(this, "warsowbunny_backtosideratio");
+       STAT(MOVEVARS_FRICTION, this) = Physics_ClientOption(this, "friction");
+       STAT(MOVEVARS_ACCELERATE, this) = Physics_ClientOption(this, "accelerate");
+       STAT(MOVEVARS_STOPSPEED, this) = Physics_ClientOption(this, "stopspeed");
+       STAT(MOVEVARS_AIRACCELERATE, this) = Physics_ClientOption(this, "airaccelerate");
+       STAT(MOVEVARS_AIRSTOPACCELERATE, this) = Physics_ClientOption(this, "airstopaccelerate");
+       STAT(MOVEVARS_JUMPVELOCITY, this) = Physics_ClientOption(this, "jumpvelocity");
+       STAT(MOVEVARS_TRACK_CANJUMP, this) = Physics_ClientOption(this, "track_canjump");
 }
 #endif
 
@@ -185,8 +80,6 @@ float GeomLerp(float a, float lerp, float b)
                : a * pow(fabs(b / a), lerp);
 }
 
-noref float pmove_waterjumptime;
-
 #define unstick_offsets(X) \
 /* 1 no nudge (just return the original if this test passes) */ \
        X(' 0.000  0.000  0.000') \
@@ -227,8 +120,10 @@ void PM_ClientMovement_Unstick(entity this)
 
 void PM_ClientMovement_UpdateStatus(entity this, bool ground)
 {
+#ifdef CSQC
        // make sure player is not stuck
-       PM_ClientMovement_Unstick(this);
+       if(autocvar_cl_movement != 3)
+               PM_ClientMovement_Unstick(this);
 
        // set crouched
        if (PHYS_INPUT_BUTTON_CROUCH(this))
@@ -250,7 +145,7 @@ void PM_ClientMovement_UpdateStatus(entity this, bool ground)
        vector origin1 = this.origin + '0 0 1';
        vector origin2 = this.origin - '0 0 1';
 
-       if (ground)
+       if (ground && autocvar_cl_movement != 3)
        {
                tracebox(origin1, this.mins, this.maxs, origin2, MOVE_NORMAL, this);
                if (trace_fraction < 1.0 && trace_plane_normal.z > 0.7)
@@ -264,32 +159,36 @@ void PM_ClientMovement_UpdateStatus(entity this, bool ground)
                        UNSET_ONGROUND(this);
        }
 
-       // set watertype/waterlevel
-       origin1 = this.origin;
-       origin1.z += this.mins_z + 1;
-       this.waterlevel = WATERLEVEL_NONE;
+       if(autocvar_cl_movement != 3)
+       {
+               // set watertype/waterlevel
+               origin1 = this.origin;
+               origin1.z += this.mins_z + 1;
+               this.waterlevel = WATERLEVEL_NONE;
 
-       int thepoint = pointcontents(origin1);
+               int thepoint = pointcontents(origin1);
 
-       this.watertype = (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME);
+               this.watertype = (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME);
 
-       if (this.watertype)
-       {
-               this.waterlevel = WATERLEVEL_WETFEET;
-               origin1.z = this.origin.z + (this.mins.z + this.maxs.z) * 0.5;
-               thepoint = pointcontents(origin1);
-               if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
+               if (this.watertype)
                {
-                       this.waterlevel = WATERLEVEL_SWIMMING;
-                       origin1.z = this.origin.z + 22;
+                       this.waterlevel = WATERLEVEL_WETFEET;
+                       origin1.z = this.origin.z + (this.mins.z + this.maxs.z) * 0.5;
                        thepoint = pointcontents(origin1);
                        if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
-                               this.waterlevel = WATERLEVEL_SUBMERGED;
+                       {
+                               this.waterlevel = WATERLEVEL_SWIMMING;
+                               origin1.z = this.origin.z + 22;
+                               thepoint = pointcontents(origin1);
+                               if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME)
+                                       this.waterlevel = WATERLEVEL_SUBMERGED;
+                       }
                }
        }
 
        if (IS_ONGROUND(this) || this.velocity.z <= 0 || pmove_waterjumptime <= 0)
                pmove_waterjumptime = 0;
+#endif
 }
 
 void PM_ClientMovement_Move(entity this)
@@ -379,7 +278,7 @@ void PM_ClientMovement_Move(entity this)
                f = (this.velocity * trace1_plane_normal);
                this.velocity = this.velocity + -f * trace1_plane_normal;
        }
-       if(pmove_waterjumptime > 0)
+       if(PHYS_TELEPORT_TIME(this) > 0)
                this.velocity = primalvelocity;
 #endif
 }
@@ -621,7 +520,7 @@ bool PlayerJump(entity this)
        animdecide_setaction(this, ANIMACTION_JUMP, true);
 
        if (autocvar_g_jump_grunt)
-               WITH(entity, this, this, PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND));
+               PlayerSound(this, playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
 #endif
        return true;
 }
@@ -647,11 +546,11 @@ void CheckWaterJump(entity this)
                        this.velocity_z = 225;
                        this.flags |= FL_WATERJUMP;
                        SET_JUMP_HELD(this);
-#ifdef SVQC
-                       this.teleport_time = time + 2;  // safety net
-#elif defined(CSQC)
+               #ifdef SVQC
+                       PHYS_TELEPORT_TIME(this) = time + 2;    // safety net
+               #elif defined(CSQC)
                        pmove_waterjumptime = time + 2;
-#endif
+               #endif
                }
        }
 }
@@ -847,8 +746,6 @@ void PM_check_frozen(entity this)
 void PM_check_hitground(entity this)
 {
 #ifdef SVQC
-       if (!IS_PLAYER(this)) return; // no fall sounds for observers thank you very much
-       if (!IS_ONGROUND(this)) return;
        if (!this.wasFlying) return;
     this.wasFlying = false;
     if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
@@ -857,9 +754,32 @@ void PM_check_hitground(entity this)
     this.nextstep = time + 0.3 + random() * 0.1;
     trace_dphitq3surfaceflags = 0;
     tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
-    if ((trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS)) return;
-    entity fall = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS) ? GS_FALL_METAL : GS_FALL;
-    WITH(entity, self, this, GlobalSound(fall, CH_PLAYER, VOICETYPE_PLAYERSOUND));
+    if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS) return;
+    entity gs = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
+       ? GS_FALL_METAL
+       : GS_FALL;
+    GlobalSound(this, gs, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+#endif
+}
+
+void PM_Footsteps(entity this)
+{
+#ifdef SVQC
+       if (!g_footsteps) return;
+       if (IS_DUCKED(this)) return;
+       if (time >= this.lastground + 0.2) return;
+       if (vdist(this.velocity, <=, autocvar_sv_maxspeed * 0.6)) return;
+       if ((time > this.nextstep) || (time < (this.nextstep - 10.0)))
+       {
+               this.nextstep = time + 0.3 + random() * 0.1;
+               trace_dphitq3surfaceflags = 0;
+               tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
+               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS) return;
+               entity gs = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
+                       ? GS_STEP_METAL
+                       : GS_STEP;
+               GlobalSound(this, gs, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+       }
 #endif
 }
 
@@ -888,7 +808,7 @@ void PM_fly(entity this, float maxspd_mod)
        vector wishdir = normalize(wishvel);
        float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
 #ifdef SVQC
-       if (time >= this.teleport_time)
+       if(time >= PHYS_TELEPORT_TIME(this))
 #endif
                PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0);
        PM_ClientMovement_Move(this);
@@ -918,7 +838,9 @@ void PM_swim(entity this, float maxspd_mod)
                        {
                                this.velocity = forward * 50;
                                this.velocity_z = 310;
+                       #ifdef CSQC
                                pmove_waterjumptime = 2;
+                       #endif
                                UNSET_ONGROUND(this);
                                SET_JUMP_HELD(this);
                        }
@@ -983,7 +905,7 @@ void PM_ladder(entity this, float maxspd_mod)
        UNSET_ONGROUND(this);
 
        float g;
-       g = PHYS_GRAVITY * PHYS_INPUT_TIMELENGTH;
+       g = PHYS_GRAVITY(this) * PHYS_INPUT_TIMELENGTH;
        if (PHYS_ENTGRAVITY(this))
                g *= PHYS_ENTGRAVITY(this);
        if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
@@ -1022,9 +944,7 @@ void PM_ladder(entity this, float maxspd_mod)
        // acceleration
        vector wishdir = normalize(wishvel);
        float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod);
-#ifdef SVQC
-       if (time >= this.teleport_time)
-#endif
+       if(time >= PHYS_TELEPORT_TIME(this))
                // water acceleration
                PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this)*maxspd_mod, 1, 0, 0, 0);
        PM_ClientMovement_Move(this);
@@ -1049,7 +969,7 @@ void PM_jetpack(entity this, float maxspd_mod)
        // it is now normalized, so...
        float a_side = PHYS_JETPACK_ACCEL_SIDE;
        float a_up = PHYS_JETPACK_ACCEL_UP;
-       float a_add = PHYS_JETPACK_ANTIGRAVITY * PHYS_GRAVITY;
+       float a_add = PHYS_JETPACK_ANTIGRAVITY * PHYS_GRAVITY(this);
 
        wishvel_x *= a_side;
        wishvel_y *= a_side;
@@ -1098,7 +1018,7 @@ void PM_jetpack(entity this, float maxspd_mod)
 
        float fxy, fz;
        fxy = bound(0, 1 - (this.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE, 1);
-       if (wishvel_z - PHYS_GRAVITY > 0)
+       if (wishvel_z - PHYS_GRAVITY(this) > 0)
                fz = bound(0, 1 - this.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
        else
                fz = bound(0, 1 + this.velocity_z / PHYS_JETPACK_MAXSPEED_UP, 1);
@@ -1107,7 +1027,7 @@ void PM_jetpack(entity this, float maxspd_mod)
        fvel = vlen(wishvel);
        wishvel_x *= fxy;
        wishvel_y *= fxy;
-       wishvel_z = (wishvel_z - PHYS_GRAVITY) * fz + PHYS_GRAVITY;
+       wishvel_z = (wishvel_z - PHYS_GRAVITY(this)) * fz + PHYS_GRAVITY(this);
 
        fvel = min(1, vlen(wishvel) / best);
        if (PHYS_JETPACK_FUEL && !(ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO))
@@ -1134,7 +1054,7 @@ void PM_jetpack(entity this, float maxspd_mod)
        }
 
 #ifdef CSQC
-       float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+       float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
        if(autocvar_cl_movement != 3)
        {
                if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
@@ -1225,7 +1145,7 @@ void PM_walk(entity this, float maxspd_mod)
                this.velocity += accelspeed * wishdir;
        }
 #ifdef CSQC
-       const float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+       float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
        if(autocvar_cl_movement != 3)
        {
                if (!(GAMEPLAYFIX_NOGRAVITYONGROUND))
@@ -1252,9 +1172,9 @@ void PM_air(entity this, float buttons_prev, float maxspd_mod)
        float wishspeed = vlen(wishvel);
 
 #ifdef SVQC
-       if (time >= this.teleport_time)
-#else
-       if (pmove_waterjumptime <= 0)
+       if(time >= PHYS_TELEPORT_TIME(this))
+#elif defined(CSQC)
+       if(pmove_waterjumptime <= 0)
 #endif
        {
                float maxairspd = PHYS_MAXAIRSPEED(this) * min(maxspd_mod, 1);
@@ -1305,7 +1225,7 @@ void PM_air(entity this, float buttons_prev, float maxspd_mod)
                        CPM_PM_Aircontrol(this, wishdir, wishspeed2);
        }
 #ifdef CSQC
-       float g = PHYS_GRAVITY * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
+       float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH;
        if(autocvar_cl_movement != 3)
        if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
                this.velocity_z -= g * 0.5;
@@ -1479,15 +1399,15 @@ void PM_Main(entity this)
                stuffcmd(this, strcat("cl_upspeed ", temps, "\n"));
        }
 
-       if(this.stat_jumpspeedcap_min != PHYS_JUMPSPEEDCAP_MIN)
+       if(this.jumpspeedcap_min != autocvar_sv_jumpspeedcap_min)
        {
-               this.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MIN;
-               stuffcmd(this, strcat("cl_jumpspeedcap_min ", PHYS_JUMPSPEEDCAP_MIN, "\n"));
+               this.jumpspeedcap_min = autocvar_sv_jumpspeedcap_min;
+               stuffcmd(this, sprintf("\ncl_jumpspeedcap_min \"%s\"\n", autocvar_sv_jumpspeedcap_min));
        }
-       if(this.stat_jumpspeedcap_max != PHYS_JUMPSPEEDCAP_MAX)
+       if(this.jumpspeedcap_max != autocvar_sv_jumpspeedcap_max)
        {
-               this.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MAX;
-               stuffcmd(this, strcat("cl_jumpspeedcap_max ", PHYS_JUMPSPEEDCAP_MAX, "\n"));
+               this.jumpspeedcap_max = autocvar_sv_jumpspeedcap_max;
+               stuffcmd(this, sprintf("\ncl_jumpspeedcap_max \"%s\"\n", autocvar_sv_jumpspeedcap_max));
        }
 #endif
 
@@ -1511,7 +1431,11 @@ void PM_Main(entity this)
                this.angles = '0 1 0' * this.v_angle.y;
 #endif
 
-       PM_check_hitground(this);
+       if (IS_PLAYER(this) && IS_ONGROUND(this))
+       {
+               PM_check_hitground(this);
+               PM_Footsteps(this);
+       }
 
        if(IsFlying(this))
                this.wasFlying = 1;
@@ -1523,17 +1447,21 @@ void PM_Main(entity this)
        {
                this.velocity_x = this.movedir.x;
                this.velocity_y = this.movedir.y;
-               if (time > this.teleport_time || this.waterlevel == WATERLEVEL_NONE)
+               if (time > PHYS_TELEPORT_TIME(this) || this.waterlevel == WATERLEVEL_NONE)
                {
                        this.flags &= ~FL_WATERJUMP;
-                       this.teleport_time = 0;
+                       PHYS_TELEPORT_TIME(this) = 0;
                }
        }
 
        else if (MUTATOR_CALLHOOK(PM_Physics, this, maxspeed_mod))
                { }
 
+#ifdef SVQC
        else if (this.movetype == MOVETYPE_NOCLIP || this.movetype == MOVETYPE_FLY || this.movetype == MOVETYPE_FLY_WORLDONLY || MUTATOR_CALLHOOK(IsFlying, this))
+#elif defined(CSQC)
+       else if (this.move_movetype == MOVETYPE_NOCLIP || this.move_movetype == MOVETYPE_FLY || this.move_movetype == MOVETYPE_FLY_WORLDONLY || MUTATOR_CALLHOOK(IsFlying, this))
+#endif
                PM_fly(this, maxspeed_mod);
 
        else if (this.waterlevel >= WATERLEVEL_SWIMMING)
@@ -1579,10 +1507,4 @@ void CSQC_ClientMovement_PlayerMove_Frame(entity this)
        SELFPARAM();
 #endif
        PM_Main(this);
-#ifdef CSQC
-       this.pmove_flags =
-                       ((this.flags & FL_DUCKED) ? PMF_DUCKED : 0) |
-                       (!(this.flags & FL_JUMPRELEASED) ? PMF_JUMP_HELD : 0) |
-                       ((this.flags & FL_ONGROUND) ? PMF_ONGROUND : 0);
-#endif
 }
index a9ad9f3eb688b5d7a86a96291be8b493c55ee6f8..6ea77fda90c7be395b29e83d87fc533b4b89b107 100644 (file)
@@ -24,8 +24,78 @@ float AdjustAirAccelQW(float accelqw, float factor);
 
 bool IsFlying(entity a);
 
+#define BUFFS_STAT(s)                       STAT(BUFFS, s)
+
+#define GAMEPLAYFIX_DOWNTRACEONGROUND       STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, this)
+#define GAMEPLAYFIX_EASIERWATERJUMP         STAT(GAMEPLAYFIX_EASIERWATERJUMP, this)
+#define GAMEPLAYFIX_STEPDOWN                STAT(GAMEPLAYFIX_STEPDOWN, this)
+#define GAMEPLAYFIX_STEPMULTIPLETIMES       STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, this)
+#define GAMEPLAYFIX_UNSTICKPLAYERS          STAT(GAMEPLAYFIX_UNSTICKPLAYERS, this)
+
+#define PHYS_ACCELERATE(s)                  STAT(MOVEVARS_ACCELERATE, s)
+#define PHYS_AIRACCELERATE(s)               STAT(MOVEVARS_AIRACCELERATE, s)
+#define PHYS_AIRACCEL_QW(s)                 STAT(MOVEVARS_AIRACCEL_QW, s)
+#define PHYS_AIRACCEL_QW_STRETCHFACTOR(s)   STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, s)
+#define PHYS_AIRACCEL_SIDEWAYS_FRICTION(s)  STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, s)
+#define PHYS_AIRCONTROL(s)                  STAT(MOVEVARS_AIRCONTROL, s)
+#define PHYS_AIRCONTROL_PENALTY(s)          STAT(MOVEVARS_AIRCONTROL_PENALTY, s)
+#define PHYS_AIRCONTROL_POWER(s)            STAT(MOVEVARS_AIRCONTROL_POWER, s)
+#define PHYS_AIRSPEEDLIMIT_NONQW(s)         STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, s)
+#define PHYS_AIRSTOPACCELERATE(s)           STAT(MOVEVARS_AIRSTOPACCELERATE, s)
+#define PHYS_AIRSTRAFEACCELERATE(s)         STAT(MOVEVARS_AIRSTRAFEACCELERATE, s)
+#define PHYS_AIRSTRAFEACCEL_QW(s)           STAT(MOVEVARS_AIRSTRAFEACCEL_QW, s)
+
+#define PHYS_AMMO_FUEL(s)                   STAT(FUEL, s)
+
+#define PHYS_DODGING_FROZEN                                    STAT(DODGING_FROZEN, this)
+
+#define PHYS_FRICTION(s)                    STAT(MOVEVARS_FRICTION, s)
+#define PHYS_FRICTION_ONLAND                STAT(MOVEVARS_FRICTION_ONLAND, this)
+#define PHYS_FRICTION_SLICK                 STAT(MOVEVARS_FRICTION_SLICK, this)
+
+#define PHYS_FROZEN(s)                      STAT(FROZEN, s)
+
+#define PHYS_HIGHSPEED                      STAT(MOVEVARS_HIGHSPEED, this)
+
+#define PHYS_JETPACK_ACCEL_SIDE                        STAT(JETPACK_ACCEL_SIDE, this)
+#define PHYS_JETPACK_ACCEL_UP                          STAT(JETPACK_ACCEL_UP, this)
+#define PHYS_JETPACK_ANTIGRAVITY                       STAT(JETPACK_ANTIGRAVITY, this)
+#define PHYS_JETPACK_FUEL                                      STAT(JETPACK_FUEL, this)
+#define PHYS_JETPACK_MAXSPEED_SIDE                     STAT(JETPACK_MAXSPEED_SIDE, this)
+#define PHYS_JETPACK_MAXSPEED_UP                       STAT(JETPACK_MAXSPEED_UP, this)
+
+#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS   STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, this)
+#define PHYS_JUMPSTEP                                          STAT(MOVEVARS_JUMPSTEP, this)
+#define PHYS_JUMPVELOCITY(s)                STAT(MOVEVARS_JUMPVELOCITY, s)
+
+#define PHYS_MAXAIRSPEED(s)                 STAT(MOVEVARS_MAXAIRSPEED, s)
+#define PHYS_MAXAIRSTRAFESPEED(s)           STAT(MOVEVARS_MAXAIRSTRAFESPEED, s)
+#define PHYS_MAXSPEED(s)                    STAT(MOVEVARS_MAXSPEED, s)
+
+#define PHYS_NOSTEP                                                    STAT(NOSTEP, this)
+#define PHYS_STEPHEIGHT                     STAT(MOVEVARS_STEPHEIGHT, this)
+
+#define PHYS_STOPSPEED(s)                   STAT(MOVEVARS_STOPSPEED, s)
+
+#define PHYS_TRACK_CANJUMP(s)               STAT(MOVEVARS_TRACK_CANJUMP, s)
+
+#define PHYS_WALLFRICTION                                      STAT(MOVEVARS_WALLFRICTION, this)
+
+#define PHYS_WARSOWBUNNY_ACCEL(s)           STAT(MOVEVARS_WARSOWBUNNY_ACCEL, s)
+#define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s) STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, s)
+#define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s) STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, s)
+#define PHYS_WARSOWBUNNY_TOPSPEED(s)        STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, s)
+#define PHYS_WARSOWBUNNY_TURNACCEL(s)       STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, s)
+
+#define UPWARD_VELOCITY_CLEARS_ONGROUND     STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, this)
+
 #ifdef CSQC
 
+       string autocvar_cl_jumpspeedcap_min;
+       string autocvar_cl_jumpspeedcap_max;
+
+       noref float pmove_waterjumptime;
+
        const int FL_WATERJUMP = 2048;  // player jumping out of water
        const int FL_JUMPRELEASED = 4096;       // for jump debouncing
 
@@ -39,11 +109,18 @@ bool IsFlying(entity a);
 // TODO
        #define IS_CLIENT(s)                                            (s).isplayermodel
        #define IS_PLAYER(s)                                            (s).isplayermodel
+       #define IS_NOT_A_CLIENT(s)                                 !(s).isplayermodel
        #define isPushable(s)                                           (s).isplayermodel
 
        //float player_multijump;
        //float player_jumpheight;
 
+       #define PHYS_GRAVITY(s)                     STAT(MOVEVARS_GRAVITY, s)
+
+       #define PHYS_TELEPORT_TIME(s)                           s.teleport_time
+
+       #define TICRATE ticrate
+
        #define PHYS_INPUT_ANGLES(s)                            input_angles
 // TODO
        #define PHYS_WORLD_ANGLES(s)                            input_angles
@@ -69,14 +146,9 @@ bool IsFlying(entity a);
 
        #define PHYS_DEAD(s)                                            s.csqcmodel_isdead
 
-       #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE  boolean(moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
-       #define GAMEPLAYFIX_NOGRAVITYONGROUND                   cvar("sv_gameplayfix_nogravityonground")
-       #define GAMEPLAYFIX_Q2AIRACCELERATE                             cvar("sv_gameplayfix_q2airaccelerate")
-       #define GAMEPLAYFIX_EASIERWATERJUMP                     getstati(STAT_GAMEPLAYFIX_EASIERWATERJUMP)
-       #define GAMEPLAYFIX_DOWNTRACEONGROUND                   getstati(STAT_GAMEPLAYFIX_DOWNTRACEONGROUND)
-       #define GAMEPLAYFIX_STEPMULTIPLETIMES                   getstati(STAT_GAMEPLAYFIX_STEPMULTIPLETIMES)
-       #define GAMEPLAYFIX_UNSTICKPLAYERS                              getstati(STAT_GAMEPLAYFIX_UNSTICKPLAYERS)
-       #define GAMEPLAYFIX_STEPDOWN                                    getstati(STAT_GAMEPLAYFIX_STEPDOWN)
+       #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE  (boolean(moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE))
+       #define GAMEPLAYFIX_NOGRAVITYONGROUND                   (boolean(moveflags & MOVEFLAG_NOGRAVITYONGROUND))
+       #define GAMEPLAYFIX_Q2AIRACCELERATE                             (boolean(moveflags & MOVEFLAG_Q2AIRACCELERATE))
 
        #define IS_DUCKED(s)                                            boolean(s.flags & FL_DUCKED)
        #define SET_DUCKED(s)                                           s.flags |= FL_DUCKED
@@ -93,124 +165,30 @@ bool IsFlying(entity a);
        #define WAS_ONGROUND(s)                                         boolean(s.lastflags & FL_ONGROUND)
 
        #define ITEMS_STAT(s)                                           (s).items
-       #define BUFFS_STAT(s)                                           getstati(STAT_BUFFS)
-
-       #define PHYS_AMMO_FUEL(s)                                       getstati(STAT_FUEL)
-
-       #define PHYS_FROZEN(s)                                          getstati(STAT_FROZEN)
-
-       #define PHYS_JUMPSPEEDCAP_MIN                           cvar_string("cl_jumpspeedcap_min")
-       #define PHYS_JUMPSPEEDCAP_MAX                           cvar_string("cl_jumpspeedcap_max")
-       #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS       getstati(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS)
-
-       #define PHYS_CL_TRACK_CANJUMP(s)                        getstati(STAT_MOVEVARS_CL_TRACK_CANJUMP)
-       #define PHYS_TRACK_CANJUMP(s)                           getstati(STAT_MOVEVARS_TRACK_CANJUMP)
-       #define PHYS_ACCELERATE(s)                                      getstatf(STAT_MOVEVARS_ACCELERATE)
-       #define PHYS_AIRACCEL_QW(s)                                     getstatf(STAT_MOVEVARS_AIRACCEL_QW)
-       #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s)       getstatf(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR)
-       #define PHYS_AIRACCEL_SIDEWAYS_FRICTION(s)      getstatf(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION)
-       #define PHYS_AIRACCELERATE(s)                           getstatf(STAT_MOVEVARS_AIRACCELERATE)
-       #define PHYS_AIRCONTROL(s)                                      getstatf(STAT_MOVEVARS_AIRCONTROL)
-       #define PHYS_AIRCONTROL_PENALTY(s)                      getstatf(STAT_MOVEVARS_AIRCONTROL_PENALTY)
-       #define PHYS_AIRCONTROL_POWER(s)                        getstatf(STAT_MOVEVARS_AIRCONTROL_POWER)
-       #define PHYS_AIRSPEEDLIMIT_NONQW(s)                     getstatf(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW)
-       #define PHYS_AIRSTOPACCELERATE(s)                       getstatf(STAT_MOVEVARS_AIRSTOPACCELERATE)
-       #define PHYS_AIRSTRAFEACCEL_QW(s)                       getstatf(STAT_MOVEVARS_AIRSTRAFEACCEL_QW)
-       #define PHYS_AIRSTRAFEACCELERATE(s)                     getstatf(STAT_MOVEVARS_AIRSTRAFEACCELERATE)
-       #define PHYS_ENTGRAVITY(s)                                      getstatf(STAT_MOVEVARS_ENTGRAVITY)
-       #define PHYS_FRICTION(s)                                        getstatf(STAT_MOVEVARS_FRICTION)
-       #define PHYS_FRICTION_SLICK                                     getstatf(STAT_MOVEVARS_FRICTION_SLICK)
-       #define PHYS_FRICTION_ONLAND                            getstatf(STAT_MOVEVARS_FRICTION_ONLAND)
-       #define PHYS_GRAVITY                                            getstatf(STAT_MOVEVARS_GRAVITY)
-       #define PHYS_HIGHSPEED                                          getstatf(STAT_MOVEVARS_HIGHSPEED)
-       #define PHYS_JUMPVELOCITY(s)                            getstatf(STAT_MOVEVARS_JUMPVELOCITY)
-       #define PHYS_MAXAIRSPEED(s)                                     getstatf(STAT_MOVEVARS_MAXAIRSPEED)
-       #define PHYS_MAXAIRSTRAFESPEED(s)                       getstatf(STAT_MOVEVARS_MAXAIRSTRAFESPEED)
-       #define PHYS_MAXSPEED(s)                                        getstatf(STAT_MOVEVARS_MAXSPEED)
-       #define PHYS_STEPHEIGHT                                         getstatf(STAT_MOVEVARS_STEPHEIGHT)
-       #define PHYS_STOPSPEED(s)                                       getstatf(STAT_MOVEVARS_STOPSPEED)
-       #define PHYS_WARSOWBUNNY_ACCEL(s)                       getstatf(STAT_MOVEVARS_WARSOWBUNNY_ACCEL)
-       #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s)     getstatf(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO)
-       #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s)     getstatf(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL)
-       #define PHYS_WARSOWBUNNY_TOPSPEED(s)            getstatf(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED)
-       #define PHYS_WARSOWBUNNY_TURNACCEL(s)           getstatf(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL)
-
-       #define PHYS_WALLFRICTION                                       getstati(STAT_MOVEVARS_WALLFRICTION)
-
-       #define PHYS_JETPACK_ACCEL_UP                           getstatf(STAT_JETPACK_ACCEL_UP)
-       #define PHYS_JETPACK_ACCEL_SIDE                         getstatf(STAT_JETPACK_ACCEL_SIDE)
-       #define PHYS_JETPACK_ANTIGRAVITY                        getstatf(STAT_JETPACK_ANTIGRAVITY)
-       #define PHYS_JETPACK_FUEL                                       getstatf(STAT_JETPACK_FUEL)
-       #define PHYS_JETPACK_MAXSPEED_UP                        getstatf(STAT_JETPACK_MAXSPEED_UP)
-       #define PHYS_JETPACK_MAXSPEED_SIDE                      getstatf(STAT_JETPACK_MAXSPEED_SIDE)
-
-       #define PHYS_DODGING_FROZEN                                     getstati(STAT_DODGING_FROZEN)
-
-       #define PHYS_NOSTEP                                                     getstati(STAT_NOSTEP)
-       #define PHYS_JUMPSTEP                                           getstati(STAT_MOVEVARS_JUMPSTEP)
+
+       #define PHYS_JUMPSPEEDCAP_MIN                           autocvar_cl_jumpspeedcap_min
+       #define PHYS_JUMPSPEEDCAP_MAX                           autocvar_cl_jumpspeedcap_max
+
+       #define PHYS_CL_TRACK_CANJUMP(s)            STAT(MOVEVARS_CL_TRACK_CANJUMP, s)
+       // FIXME: 0 doesn't mean zero gravity
+       #define PHYS_ENTGRAVITY(s)                  STAT(MOVEVARS_ENTGRAVITY, s)
 
 #elif defined(SVQC)
 
        bool Physics_Valid(string thecvar);
 
-       .vector stat_pl_view_ofs;
-       .vector stat_pl_crouch_view_ofs;
-
-       .vector stat_pl_min;
-       .vector stat_pl_max;
-       .vector stat_pl_crouch_min;
-       .vector stat_pl_crouch_max;
-
-       .float stat_sv_airaccel_qw;
-       .float stat_sv_airstrafeaccel_qw;
-       .float stat_sv_airspeedlimit_nonqw;
-       .float stat_sv_maxspeed;
-       .float stat_movement_highspeed;
-
-       .float stat_sv_friction_on_land;
-       .float stat_sv_friction_slick;
-
-       .string stat_jumpspeedcap_min;
-       .string stat_jumpspeedcap_max;
-       .float stat_jumpspeedcap_disable_onramps;
-
-       .float stat_jetpack_accel_side;
-       .float stat_jetpack_accel_up;
-       .float stat_jetpack_antigravity;
-       .float stat_jetpack_fuel;
-       .float stat_jetpack_maxspeed_up;
-       .float stat_jetpack_maxspeed_side;
-       .float stat_gameplayfix_easierwaterjump;
-       .float stat_gameplayfix_downtracesupportsongroundflag;
-       .float stat_gameplayfix_stepmultipletimes;
-       .float stat_gameplayfix_unstickplayers;
-       .float stat_gameplayfix_stepdown;
-
-       // new properties
-       .float stat_sv_jumpvelocity;
-       .float stat_sv_airaccel_qw_stretchfactor;
-       .float stat_sv_maxairstrafespeed;
-       .float stat_sv_maxairspeed;
-       .float stat_sv_airstrafeaccelerate;
-       .float stat_sv_warsowbunny_turnaccel;
-       .float stat_sv_airaccel_sideways_friction;
-       .float stat_sv_aircontrol;
-       .float stat_sv_aircontrol_power;
-       .float stat_sv_aircontrol_penalty;
-       .float stat_sv_warsowbunny_airforwardaccel;
-       .float stat_sv_warsowbunny_topspeed;
-       .float stat_sv_warsowbunny_accel;
-       .float stat_sv_warsowbunny_backtosideratio;
-       .float stat_sv_friction;
-       .float stat_sv_accelerate;
-       .float stat_sv_stopspeed;
-       .float stat_sv_airaccelerate;
-       .float stat_sv_airstopaccelerate;
-
-       .float stat_nostep;
-       .float stat_jumpstep;
-
-       .bool stat_sv_track_canjump;
+       .float stat_sv_airspeedlimit_nonqw = _STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW);
+       .float stat_sv_maxspeed = _STAT(MOVEVARS_MAXSPEED);
+
+       /** Not real stats */
+       .string jumpspeedcap_min;
+       .string jumpspeedcap_max;
+
+       #define PHYS_TELEPORT_TIME(s)                           s.teleport_time
+
+       #define PHYS_GRAVITY(s)                     autocvar_sv_gravity
+
+       #define TICRATE sys_frametime
 
        #define PHYS_INPUT_ANGLES(s)                            s.v_angle
        #define PHYS_WORLD_ANGLES(s)                            s.angles
@@ -237,13 +215,8 @@ bool IsFlying(entity a);
        #define PHYS_DEAD(s)                                            s.deadflag != DEAD_NO
 
        #define GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE  autocvar_sv_gameplayfix_gravityunaffectedbyticrate
-       #define GAMEPLAYFIX_NOGRAVITYONGROUND                   cvar("sv_gameplayfix_nogravityonground")
+       #define GAMEPLAYFIX_NOGRAVITYONGROUND                   autocvar_sv_gameplayfix_nogravityonground
        #define GAMEPLAYFIX_Q2AIRACCELERATE                             autocvar_sv_gameplayfix_q2airaccelerate
-       #define GAMEPLAYFIX_EASIERWATERJUMP                             cvar("sv_gameplayfix_easierwaterjump")
-       #define GAMEPLAYFIX_DOWNTRACEONGROUND                   cvar("sv_gameplayfix_downtracesupportsongroundflag")
-       #define GAMEPLAYFIX_STEPMULTIPLETIMES                   cvar("sv_gameplayfix_stepmultipletimes")
-       #define GAMEPLAYFIX_UNSTICKPLAYERS                              cvar("sv_gameplayfix_unstickplayers")
-       #define GAMEPLAYFIX_STEPDOWN                                    cvar("sv_gameplayfix_stepdown")
 
        #define IS_DUCKED(s)                                            s.crouch
        #define SET_DUCKED(s)                                           s.crouch = true
@@ -260,61 +233,12 @@ bool IsFlying(entity a);
        #define WAS_ONGROUND(s)                                         boolean((s).lastflags & FL_ONGROUND)
 
        #define ITEMS_STAT(s)                                           s.items
-       #define BUFFS_STAT(s)                                           (s).buffs
-
-       #define PHYS_AMMO_FUEL(s)                                       s.ammo_fuel
-
-       #define PHYS_FROZEN(s)                                          s.frozen
 
        #define PHYS_JUMPSPEEDCAP_MIN                           autocvar_sv_jumpspeedcap_min
        #define PHYS_JUMPSPEEDCAP_MAX                           autocvar_sv_jumpspeedcap_max
-       #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS       autocvar_sv_jumpspeedcap_max_disable_on_ramps
 
        #define PHYS_CL_TRACK_CANJUMP(s)                        s.cvar_cl_movement_track_canjump
-       #define PHYS_TRACK_CANJUMP(s)                           s.stat_sv_track_canjump
-       #define PHYS_ACCELERATE(s)                                      s.stat_sv_accelerate
-       #define PHYS_AIRACCEL_QW(s)                                     s.stat_sv_airaccel_qw
-       #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s)       s.stat_sv_airaccel_qw_stretchfactor
-       #define PHYS_AIRACCEL_SIDEWAYS_FRICTION(s)      s.stat_sv_airaccel_sideways_friction
-       #define PHYS_AIRACCELERATE(s)                           s.stat_sv_airaccelerate
-       #define PHYS_AIRCONTROL(s)                                      s.stat_sv_aircontrol
-       #define PHYS_AIRCONTROL_PENALTY(s)                      s.stat_sv_aircontrol_penalty
-       #define PHYS_AIRCONTROL_POWER(s)                        s.stat_sv_aircontrol_power
-       #define PHYS_AIRSPEEDLIMIT_NONQW(s)                     s.stat_sv_airspeedlimit_nonqw
-       #define PHYS_AIRSTOPACCELERATE(s)                       s.stat_sv_airstopaccelerate
-       #define PHYS_AIRSTRAFEACCEL_QW(s)                       s.stat_sv_airstrafeaccel_qw
-       #define PHYS_AIRSTRAFEACCELERATE(s)                     s.stat_sv_airstrafeaccelerate
        #define PHYS_ENTGRAVITY(s)                                      s.gravity
-       #define PHYS_FRICTION(s)                                        s.stat_sv_friction
-       #define PHYS_FRICTION_SLICK                                     autocvar_sv_friction_slick
-       #define PHYS_FRICTION_ONLAND                            autocvar_sv_friction_on_land
-       #define PHYS_GRAVITY                                            autocvar_sv_gravity
-       #define PHYS_HIGHSPEED                                          autocvar_g_movement_highspeed
-       #define PHYS_JUMPVELOCITY(s)                            s.stat_sv_jumpvelocity
-       #define PHYS_MAXAIRSPEED(s)                                     s.stat_sv_maxairspeed
-       #define PHYS_MAXAIRSTRAFESPEED(s)                       s.stat_sv_maxairstrafespeed
-       #define PHYS_MAXSPEED(s)                                        s.stat_sv_maxspeed
-       #define PHYS_STEPHEIGHT                                         autocvar_sv_stepheight
-       #define PHYS_STOPSPEED(s)                                       s.stat_sv_stopspeed
-       #define PHYS_WARSOWBUNNY_ACCEL(s)                       s.stat_sv_warsowbunny_accel
-       #define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s)s.stat_sv_warsowbunny_backtosideratio
-       #define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s)s.stat_sv_warsowbunny_airforwardaccel
-       #define PHYS_WARSOWBUNNY_TOPSPEED(s)            s.stat_sv_warsowbunny_topspeed
-       #define PHYS_WARSOWBUNNY_TURNACCEL(s)           s.stat_sv_warsowbunny_turnaccel
-
-       #define PHYS_WALLFRICTION                                       cvar("sv_wallfriction")
-
-       #define PHYS_JETPACK_ACCEL_UP                           autocvar_g_jetpack_acceleration_up
-       #define PHYS_JETPACK_ACCEL_SIDE                         autocvar_g_jetpack_acceleration_side
-       #define PHYS_JETPACK_ANTIGRAVITY                        autocvar_g_jetpack_antigravity
-       #define PHYS_JETPACK_FUEL                                       autocvar_g_jetpack_fuel
-       #define PHYS_JETPACK_MAXSPEED_UP                        autocvar_g_jetpack_maxspeed_up
-       #define PHYS_JETPACK_MAXSPEED_SIDE                      autocvar_g_jetpack_maxspeed_side
-
-       #define PHYS_DODGING_FROZEN                                     autocvar_sv_dodging_frozen
-
-       #define PHYS_NOSTEP                                                     cvar("sv_nostep")
-       #define PHYS_JUMPSTEP                                           cvar("sv_jumpstep")
 
 #endif
 #endif
index 7584e3353c081c50fe7768682f81ec871d5e08d5..2d9398ad7ede56de2b00681aa9fa5fd65c62ad2a 100644 (file)
@@ -106,23 +106,16 @@ float PlayerStats_GameReport_Event(string prefix, string event_id, float value)
 
 void PlayerStats_GameReport_Accuracy(entity p)
 {
-       int i;
-
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-       {
-               entity w = get_weaponinfo(i);
-
-               #define ACCMAC(suffix,field) \
-                       PS_GR_P_ADDVAL(p, sprintf("acc-%s-%s", w.netname, suffix), p.accuracy.(field[i-1]));
-
+       #define ACCMAC(suffix, field) \
+               PS_GR_P_ADDVAL(p, sprintf("acc-%s-%s", it.netname, suffix), p.accuracy.(field[i-1]));
+       FOREACH(Weapons, it != WEP_Null, LAMBDA(
                ACCMAC("hit", accuracy_hit)
                ACCMAC("fired", accuracy_fired)
                ACCMAC("cnt-hit", accuracy_cnt_hit)
                ACCMAC("cnt-fired", accuracy_cnt_fired)
                ACCMAC("frags", accuracy_frags)
-
-               #undef ACCMAC
-       }
+       ));
+       #undef ACCMAC
 }
 
 void PlayerStats_GameReport_FinalizePlayer(entity p)
@@ -240,17 +233,13 @@ void PlayerStats_GameReport_Init() // initiated before InitGameplayMode so that
                PlayerStats_GameReport_AddEvent(PLAYERSTATS_RANK);
 
                // accuracy stats
-               entity w;
-               float i;
-               for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-               {
-                       w = get_weaponinfo(i);
-                       PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-hit"));
-                       PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-fired"));
-                       PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-cnt-hit"));
-                       PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-cnt-fired"));
-                       PlayerStats_GameReport_AddEvent(strcat("acc-", w.netname, "-frags"));
-               }
+               FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                       PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-hit"));
+                       PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-fired"));
+                       PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-cnt-hit"));
+                       PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-cnt-fired"));
+                       PlayerStats_GameReport_AddEvent(strcat("acc-", it.netname, "-frags"));
+               ));
 
                PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3);
                PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5);
index 503290b6c03f916fbd0972eba1f767cef0360e5c..1e02758580b7a7e2c982fd36dbd3019013809a61 100644 (file)
@@ -67,13 +67,27 @@ const float VOL_BASEVOICE = 1.0;
 #define sound8(e, o, chan, samp, vol, atten, speed, sf) \
        do \
        { \
-               entity __e = e; \
+               entity __e; \
+               int __chan = chan; \
+               string __samp = samp; \
+               bool auto = false; \
+               if (__chan > 0) __e = e; \
+               else \
+               { \
+                       auto = true; \
+                       __chan = fabs(__chan); \
+                       entity tmp = __e = new(csqc_autochannel); \
+                       make_pure(tmp); \
+                       tmp.think = SUB_Remove_self; \
+                       tmp.nextthink = time + soundlength(__samp); \
+               } \
                vector old_origin = __e.origin; \
                vector old_mins = __e.mins; \
                vector old_maxs = __e.maxs; \
                setorigin(__e, o); \
                setsize(__e, '0 0 0', '0 0 0'); \
-               sound7(__e, chan, samp, vol, atten, speed, sf); \
+               sound7(__e, __chan, __samp, vol, atten, speed, sf); \
+               if (auto) break; \
                setorigin(__e, old_origin); \
                setsize(__e, old_mins, old_maxs); \
        } \
@@ -96,18 +110,24 @@ CLASS(Sound, Object)
                        x(ogg) \
                        x(flac) \
                        /**/
-               string full, relative;
-               #define tryext(ext) { if (fexists(full = strcat("sound/", relative = strcat(base, "." #ext)))) break; }
+               string relative;
+               #define tryext(ext) { if (fexists(strcat("sound/", relative = strcat(base, "." #ext)))) break; }
                do
                {
                        extensions(tryext);
 #undef tryext
 #undef extensions
-                       LOG_WARNINGF("Missing sound: \"%s\"\n", full);
+                       LOG_WARNINGF("Missing sound: \"%s\"\n", strcat("sound/", base));
+#ifdef CSQC
                        return string_null;
+#endif
                }
                while (0);
+#ifdef SVQC
+               return strcat(base, ".wav");  // let the client engine decide
+#else
                return relative;
+#endif
        }
        METHOD(Sound, sound_precache, void(entity this))
        {
index ed3d077f9c3cc8e62e515ffb59f0f409a5bf2168..d52329333ca400399984919a8e7857cb0ce1007b 100644 (file)
 #ifndef STATS_H
 #define STATS_H
 
+#ifdef SVQC
+#include "../server/cl_client.qh"
+#endif
+
 // Full list of all stat constants, included in a single location for easy reference
 // 255 is the current limit (MAX_CL_STATS - 1), engine will need to be modified if you wish to add more stats
 
-const int MAX_CL_STATS                = 256;
-// -Wdouble-declaration
-// const int STAT_HEALTH                 = 0;
-// 1 empty?
-const int STAT_WEAPON                 = 2;
-// -Wdouble-declaration
-// const int STAT_AMMO                   = 3;
-// -Wdouble-declaration
-// const int STAT_ARMOR                  = 4;
-// -Wdouble-declaration
-// const int STAT_WEAPONFRAME            = 5;
-// -Wdouble-declaration
-// const int STAT_SHELLS                 = 6;
-// -Wdouble-declaration
-// const int STAT_NAILS                  = 7;
-// -Wdouble-declaration
-// const int STAT_ROCKETS                = 8;
-// -Wdouble-declaration
-// const int STAT_CELLS                  = 9;
-// -Wdouble-declaration
-// const int STAT_ACTIVEWEAPON           = 10;
-// -Wdouble-declaration
-// const int STAT_TOTALSECRETS           = 11;
-// -Wdouble-declaration
-// const int STAT_TOTALMONSTERS          = 12;
-// -Wdouble-declaration
-// const int STAT_SECRETS                = 13;
-// -Wdouble-declaration
-// const int STAT_MONSTERS               = 14;
-// -Wdouble-declaration
-// const int STAT_ITEMS                  = 15;
-// -Wdouble-declaration
-// const int STAT_VIEWHEIGHT             = 16;
-// 17 empty?
-// 18 empty?
-// 19 empty?
-// 20 empty?
-const int STAT_VIEWZOOM               = 21;
-// 22 empty?
-// 23 empty?
-// 24 empty?
-// 25 empty?
-// 26 empty?
-// 27 empty?
-// 28 empty?
-// 29 empty?
-// 30 empty?
-// 31 empty?
-
-enum {
-    STAT_WEAPONS = 32,
-    STAT_WEAPONS2,
-    STAT_WEAPONS3,
-
-    STAT_WEAPONSINMAP,
-    STAT_WEAPONSINMAP2,
-    STAT_WEAPONSINMAP3,
-
-    STAT_PL_VIEW_OFS1,
-    STAT_PL_VIEW_OFS2,
-    STAT_PL_VIEW_OFS3,
-
-    STAT_PL_CROUCH_VIEW_OFS1,
-    STAT_PL_CROUCH_VIEW_OFS2,
-    STAT_PL_CROUCH_VIEW_OFS3,
-
-    STAT_PL_MIN1,
-    STAT_PL_MIN2,
-    STAT_PL_MIN3,
-
-    STAT_PL_MAX1,
-    STAT_PL_MAX2,
-    STAT_PL_MAX3,
+const int MAX_CL_STATS = 256;
+#ifndef CSQC
+const int STAT_HEALTH = 0; // .health
+const int STAT_ARMOR = 4; // .armorvalue
+const int STAT_SHELLS = 6; // .ammo_shells
+const int STAT_NAILS = 7; // .ammo_nails
+const int STAT_ROCKETS = 8; // .ammo_rockets
+const int STAT_CELLS = 9; // .ammo_cells
+const int STAT_ACTIVEWEAPON = 10; // .weapon
+const int STAT_ITEMS = 15; // .items | .items2 << 23 | serverflags << 28
+const int STAT_VIEWHEIGHT = 16; // .view_ofs_z
+#endif
 
-    STAT_PL_CROUCH_MIN1,
-    STAT_PL_CROUCH_MIN2,
-    STAT_PL_CROUCH_MIN3,
+REGISTER_STAT(WEAPONS, vectori)
+REGISTER_STAT(WEAPONSINMAP, vectori)
 
-    STAT_PL_CROUCH_MAX1,
-    STAT_PL_CROUCH_MAX2,
-    STAT_PL_CROUCH_MAX3,
+REGISTER_STAT(PL_VIEW_OFS, vector, autocvar_sv_player_viewoffset)
+REGISTER_STAT(PL_CROUCH_VIEW_OFS, vector, autocvar_sv_player_crouch_viewoffset)
 
-    STAT_LAST_VECTOR
-};
+REGISTER_STAT(PL_MIN, vector, autocvar_sv_player_mins)
+REGISTER_STAT(PL_CROUCH_MIN, vector, autocvar_sv_player_crouch_mins)
 
-const int REGISTERED_STATS = 6;
+REGISTER_STAT(PL_MAX, vector, autocvar_sv_player_maxs)
+REGISTER_STAT(PL_CROUCH_MAX, vector, autocvar_sv_player_crouch_maxs)
 
 REGISTER_STAT(KH_KEYS, int)
+
 /** weapon requested to switch to; next WANTED weapon (for HUD) */
 REGISTER_STAT(SWITCHWEAPON, int)
+/** weapon currently being switched to (is copied from switchweapon once switch is possible) */
+REGISTER_STAT(SWITCHINGWEAPON, int)
+REGISTER_STAT(WEAPON_NEXTTHINK, float)
+#ifdef SVQC
+SPECTATE_COPY(_STAT(WEAPON_NEXTTHINK))
+float W_WeaponRateFactor();
+#endif
+REGISTER_STAT(WEAPONRATEFACTOR, float, W_WeaponRateFactor())
+
 REGISTER_STAT(GAMESTARTTIME, float)
 REGISTER_STAT(STRENGTH_FINISHED, float)
 REGISTER_STAT(INVINCIBLE_FINISHED, float)
 /** arc heat in [0,1] */
 REGISTER_STAT(ARC_HEAT, float)
+REGISTER_STAT(PRESSED_KEYS, int)
+/** this stat could later contain some other bits of info, like, more server-side particle config */
+REGISTER_STAT(ALLOW_OLDVORTEXBEAM, bool)
+REGISTER_STAT(FUEL, int)
+REGISTER_STAT(NB_METERSTART, float)
+/** compressShotOrigin */
+REGISTER_STAT(SHOTORG, int)
+REGISTER_STAT(LEADLIMIT, float)
+REGISTER_STAT(WEAPON_CLIPLOAD, int)
+REGISTER_STAT(WEAPON_CLIPSIZE, int)
 
-enum {
-    STAT_FIRST_MAIN = (STAT_LAST_VECTOR - 1) + REGISTERED_STATS,
+REGISTER_STAT(VORTEX_CHARGE, float)
+REGISTER_STAT(LAST_PICKUP, float)
+REGISTER_STAT(HUD, int)
+REGISTER_STAT(VORTEX_CHARGEPOOL, float)
+REGISTER_STAT(HIT_TIME, float)
+REGISTER_STAT(DAMAGE_DEALT_TOTAL, int)
+REGISTER_STAT(TYPEHIT_TIME, float)
+REGISTER_STAT(LAYED_MINES, int)
+REGISTER_STAT(HAGAR_LOAD, int)
+REGISTER_STAT(SUPERWEAPONS_FINISHED, float)
+REGISTER_STAT(VEHICLESTAT_HEALTH, int)
+REGISTER_STAT(VEHICLESTAT_SHIELD, int)
+REGISTER_STAT(VEHICLESTAT_ENERGY, int)
+REGISTER_STAT(VEHICLESTAT_AMMO1, int)
+REGISTER_STAT(VEHICLESTAT_RELOAD1, int)
+REGISTER_STAT(VEHICLESTAT_AMMO2, int)
+REGISTER_STAT(VEHICLESTAT_RELOAD2, int)
+REGISTER_STAT(VEHICLESTAT_W2MODE, int)
+REGISTER_STAT(NADE_TIMER, float)
+REGISTER_STAT(SECRETS_TOTAL, float)
+REGISTER_STAT(SECRETS_FOUND, float)
+REGISTER_STAT(RESPAWN_TIME, float)
+REGISTER_STAT(ROUNDSTARTTIME, float)
+REGISTER_STAT(MONSTERS_TOTAL, int)
+REGISTER_STAT(MONSTERS_KILLED, int)
+REGISTER_STAT(BUFFS, int)
+REGISTER_STAT(NADE_BONUS, float)
+REGISTER_STAT(NADE_BONUS_TYPE, int)
+REGISTER_STAT(NADE_BONUS_SCORE, float)
+REGISTER_STAT(HEALING_ORB, float)
+REGISTER_STAT(HEALING_ORB_ALPHA, float)
+REGISTER_STAT(PLASMA, int)
+REGISTER_STAT(OK_AMMO_CHARGE, float)
+REGISTER_STAT(OK_AMMO_CHARGEPOOL, float)
+REGISTER_STAT(FROZEN, int)
+REGISTER_STAT(REVIVE_PROGRESS, float)
+REGISTER_STAT(ROUNDLOST, int)
+REGISTER_STAT(BUFF_TIME, float)
+REGISTER_STAT(CTF_FLAGSTATUS, int)
 
-    STAT_PRESSED_KEYS,
-    /** this stat could later contain some other bits of info, like, more server-side particle config */ STAT_ALLOW_OLDVORTEXBEAM,
-    STAT_FUEL,
-    STAT_NB_METERSTART,
-    /** compressShotOrigin */ STAT_SHOTORG,
-    STAT_LEADLIMIT,
-    STAT_WEAPON_CLIPLOAD,
-    STAT_WEAPON_CLIPSIZE,
-    STAT_VORTEX_CHARGE,
-    STAT_LAST_PICKUP,
-    STAT_HUD,
-    STAT_VORTEX_CHARGEPOOL,
-    STAT_HIT_TIME,
-    STAT_DAMAGE_DEALT_TOTAL,
-    STAT_TYPEHIT_TIME,
-    STAT_LAYED_MINES,
-    STAT_HAGAR_LOAD,
-    STAT_SWITCHINGWEAPON,
-    STAT_SUPERWEAPONS_FINISHED,
-    STAT_VEHICLESTAT_HEALTH,
-    STAT_VEHICLESTAT_SHIELD,
-    STAT_VEHICLESTAT_ENERGY,
-    STAT_VEHICLESTAT_AMMO1,
-    STAT_VEHICLESTAT_RELOAD1,
-    STAT_VEHICLESTAT_AMMO2,
-    STAT_VEHICLESTAT_RELOAD2,
-    STAT_VEHICLESTAT_W2MODE,
-    STAT_NADE_TIMER,
-    STAT_SECRETS_TOTAL,
-    STAT_SECRETS_FOUND,
-    STAT_RESPAWN_TIME,
-    STAT_ROUNDSTARTTIME,
-    STAT_MONSTERS_TOTAL,
-    STAT_MONSTERS_KILLED,
-    STAT_BUFFS,
-    STAT_NADE_BONUS,
-    STAT_NADE_BONUS_TYPE,
-    STAT_NADE_BONUS_SCORE,
-    STAT_HEALING_ORB,
-    STAT_HEALING_ORB_ALPHA,
-    STAT_PLASMA,
-    STAT_OK_AMMO_CHARGE,
-    STAT_OK_AMMO_CHARGEPOOL,
-    STAT_FROZEN,
-    STAT_REVIVE_PROGRESS,
-    STAT_ROUNDLOST,
-    STAT_BUFF_TIME,
-    STAT_CTF_FLAGSTATUS,
-    STAT_MULTIJUMP_DODGING,
-    STAT_MULTIJUMP_MAXSPEED,
-    STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND,
-    STAT_BUGRIGS_REVERSE_STOPPING,
-    STAT_BUGRIGS_REVERSE_SPINNING,
-    STAT_BUGRIGS_CAR_JUMPING,
-    STAT_BUGRIGS_FRICTION_AIR,
-    STAT_BUGRIGS_STEER,
-    STAT_BUGRIGS_SPEED_POW,
-    STAT_BUGRIGS_SPEED_REF,
-    STAT_BUGRIGS_ACCEL,
-    STAT_BUGRIGS_FRICTION_BRAKE,
-    STAT_BUGRIGS_AIR_STEERING,
-    STAT_BUGRIGS_FRICTION_FLOOR,
-    STAT_BUGRIGS_REVERSE_SPEEDING,
-    STAT_BUGRIGS_PLANAR_MOVEMENT,
-    STAT_BUGRIGS_ANGLE_SMOOTHING,
-    STAT_BUGRIGS,
-    STAT_GAMEPLAYFIX_STEPDOWN,
-    STAT_MOVEVARS_JUMPSTEP,
-    STAT_NOSTEP,
-    STAT_GAMEPLAYFIX_UNSTICKPLAYERS,
-    STAT_GAMEPLAYFIX_STEPMULTIPLETIMES,
-    STAT_GAMEPLAYFIX_DOWNTRACEONGROUND,
-    STAT_GAMEPLAYFIX_EASIERWATERJUMP,
-    STAT_MOVEVARS_FRICTION_SLICK,
-    STAT_MOVEVARS_FRICTION_ONLAND,
-    STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS,
-    STAT_MOVEVARS_TRACK_CANJUMP,
-    STAT_DOUBLEJUMP,
-    STAT_MOVEVARS_CL_TRACK_CANJUMP,
-    STAT_MULTIJUMP_ADD,
-    STAT_MULTIJUMP_SPEED,
-    STAT_MULTIJUMP,
-    STAT_DODGING_TIMEOUT,
-    STAT_DODGING_WALL,
-    STAT_DODGING_UP_SPEED,
-    STAT_DODGING_RAMP_TIME,
-    STAT_DODGING_HEIGHT_THRESHOLD,
-    STAT_DODGING_DISTANCE_THRESHOLD,
-    STAT_DODGING_HORIZ_SPEED,
-    STAT_DODGING_DELAY,
-    STAT_DODGING_FROZEN_NO_DOUBLETAP,
-    STAT_DODGING_HORIZ_SPEED_FROZEN,
-    STAT_DODGING,
-    STAT_DODGING_FROZEN,
-    STAT_JETPACK_MAXSPEED_UP,
-    STAT_JETPACK_MAXSPEED_SIDE,
-    STAT_JETPACK_FUEL,
-    STAT_JETPACK_ANTIGRAVITY,
-    STAT_JETPACK_ACCEL_SIDE,
-    STAT_JETPACK_ACCEL_UP,
-    STAT_MOVEVARS_HIGHSPEED,
-    STAT_MULTIJUMP_COUNT,
+#ifdef SVQC
+int autocvar_g_multijump;
+float autocvar_g_multijump_add;
+float autocvar_g_multijump_speed;
+float autocvar_g_multijump_maxspeed;
+float autocvar_g_multijump_dodging = 1;
+#endif
+REGISTER_STAT(MULTIJUMP_DODGING, int, autocvar_g_multijump_dodging)
+REGISTER_STAT(MULTIJUMP_MAXSPEED, float, autocvar_g_multijump_maxspeed)
+REGISTER_STAT(MULTIJUMP_ADD, int, autocvar_g_multijump_add)
+REGISTER_STAT(MULTIJUMP_SPEED, float, autocvar_g_multijump_speed)
+.int multijump_count;
+REGISTER_STAT(MULTIJUMP_COUNT, int, this.multijump_count)
+REGISTER_STAT(MULTIJUMP, int, autocvar_g_multijump)
+REGISTER_STAT(DOUBLEJUMP, int, autocvar_sv_doublejump)
+
+#ifdef SVQC
+bool g_bugrigs;
+bool g_bugrigs_planar_movement;
+bool g_bugrigs_planar_movement_car_jumping;
+float g_bugrigs_reverse_spinning;
+float g_bugrigs_reverse_speeding;
+float g_bugrigs_reverse_stopping;
+float g_bugrigs_air_steering;
+float g_bugrigs_angle_smoothing;
+float g_bugrigs_friction_floor;
+float g_bugrigs_friction_brake;
+float g_bugrigs_friction_air;
+float g_bugrigs_accel;
+float g_bugrigs_speed_ref;
+float g_bugrigs_speed_pow;
+float g_bugrigs_steer;
+#endif
+REGISTER_STAT(BUGRIGS, int, g_bugrigs)
+REGISTER_STAT(BUGRIGS_ACCEL, float, g_bugrigs_accel)
+REGISTER_STAT(BUGRIGS_AIR_STEERING, int, g_bugrigs_air_steering)
+REGISTER_STAT(BUGRIGS_ANGLE_SMOOTHING, int, g_bugrigs_angle_smoothing)
+REGISTER_STAT(BUGRIGS_CAR_JUMPING, int, g_bugrigs_planar_movement_car_jumping)
+REGISTER_STAT(BUGRIGS_FRICTION_AIR, float, g_bugrigs_friction_air)
+REGISTER_STAT(BUGRIGS_FRICTION_BRAKE, float, g_bugrigs_friction_brake)
+REGISTER_STAT(BUGRIGS_FRICTION_FLOOR, float, g_bugrigs_friction_floor)
+REGISTER_STAT(BUGRIGS_PLANAR_MOVEMENT, int, g_bugrigs_planar_movement)
+REGISTER_STAT(BUGRIGS_REVERSE_SPEEDING, int, g_bugrigs_reverse_speeding)
+REGISTER_STAT(BUGRIGS_REVERSE_SPINNING, int, g_bugrigs_reverse_spinning)
+REGISTER_STAT(BUGRIGS_REVERSE_STOPPING, int, g_bugrigs_reverse_stopping)
+REGISTER_STAT(BUGRIGS_SPEED_POW, float, g_bugrigs_speed_pow)
+REGISTER_STAT(BUGRIGS_SPEED_REF, float, g_bugrigs_speed_ref)
+REGISTER_STAT(BUGRIGS_STEER, float, g_bugrigs_steer)
+
+REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, cvar("sv_gameplayfix_downtracesupportsongroundflag"))
+REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, cvar("sv_gameplayfix_easierwaterjump"))
+REGISTER_STAT(GAMEPLAYFIX_STEPDOWN, int, cvar("sv_gameplayfix_stepdown"))
+REGISTER_STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, int, cvar("sv_gameplayfix_stepmultipletimes"))
+REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, cvar("sv_gameplayfix_unstickplayers"))
+REGISTER_STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, int, autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag)
+
+REGISTER_STAT(MOVEVARS_JUMPSTEP, int, cvar("sv_jumpstep"))
+REGISTER_STAT(NOSTEP, int, cvar("sv_nostep"))
+
+REGISTER_STAT(MOVEVARS_FRICTION, float)
+REGISTER_STAT(MOVEVARS_FRICTION_SLICK, float, autocvar_sv_friction_slick)
+REGISTER_STAT(MOVEVARS_FRICTION_ONLAND, float, autocvar_sv_friction_on_land)
 
-    STAT_LAST_MAIN
-};
+REGISTER_STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, int, autocvar_sv_jumpspeedcap_max_disable_on_ramps)
+REGISTER_STAT(MOVEVARS_TRACK_CANJUMP, int)
+/** cvar loopback */
+REGISTER_STAT(MOVEVARS_CL_TRACK_CANJUMP, int)
 
-const int STAT_LAST = STAT_LAST_MAIN + 5;
+#ifdef SVQC
+int g_dodging;
+float autocvar_sv_dodging_delay;
+float autocvar_sv_dodging_wall_distance_threshold;
+bool autocvar_sv_dodging_frozen;
+bool autocvar_sv_dodging_frozen_doubletap;
+float autocvar_sv_dodging_height_threshold;
+float autocvar_sv_dodging_horiz_speed;
+float autocvar_sv_dodging_horiz_speed_frozen;
+float autocvar_sv_dodging_ramp_time;
+float autocvar_sv_dodging_up_speed;
+bool autocvar_sv_dodging_wall_dodging;
+#endif
+
+REGISTER_STAT(DODGING, int, g_dodging)
+REGISTER_STAT(DODGING_DELAY, float, autocvar_sv_dodging_delay)
+REGISTER_STAT(DODGING_DISTANCE_THRESHOLD, float, autocvar_sv_dodging_wall_distance_threshold)
+REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen)
+REGISTER_STAT(DODGING_FROZEN_NO_DOUBLETAP, int, autocvar_sv_dodging_frozen_doubletap)
+REGISTER_STAT(DODGING_HEIGHT_THRESHOLD, float, autocvar_sv_dodging_height_threshold)
+REGISTER_STAT(DODGING_HORIZ_SPEED, float, autocvar_sv_dodging_horiz_speed)
+REGISTER_STAT(DODGING_HORIZ_SPEED_FROZEN, float, autocvar_sv_dodging_horiz_speed_frozen)
+REGISTER_STAT(DODGING_RAMP_TIME, float, autocvar_sv_dodging_ramp_time)
+/** cvar loopback */
+REGISTER_STAT(DODGING_TIMEOUT, float)
+REGISTER_STAT(DODGING_UP_SPEED, float, autocvar_sv_dodging_up_speed)
+REGISTER_STAT(DODGING_WALL, int, autocvar_sv_dodging_wall_dodging)
+
+REGISTER_STAT(JETPACK_ACCEL_SIDE, float, autocvar_g_jetpack_acceleration_side)
+REGISTER_STAT(JETPACK_ACCEL_UP, float, autocvar_g_jetpack_acceleration_up)
+REGISTER_STAT(JETPACK_ANTIGRAVITY, float, autocvar_g_jetpack_antigravity)
+REGISTER_STAT(JETPACK_FUEL, float, autocvar_g_jetpack_fuel)
+REGISTER_STAT(JETPACK_MAXSPEED_SIDE, float, autocvar_g_jetpack_maxspeed_side)
+REGISTER_STAT(JETPACK_MAXSPEED_UP, float, autocvar_g_jetpack_maxspeed_up)
 
-/* The following stats change depending on the gamemode, so can share the same ID */
+REGISTER_STAT(MOVEVARS_HIGHSPEED, float, autocvar_g_movement_highspeed)
 
-// freeze tag, clan arena, jailbreak
-enum {
-    STAT_REDALIVE = STAT_LAST_MAIN,
-    STAT_BLUEALIVE,
-    STAT_YELLOWALIVE,
-    STAT_PINKALIVE,
-};
+// freeze tag, clan arena
+REGISTER_STAT(REDALIVE, int)
+REGISTER_STAT(BLUEALIVE, int)
+REGISTER_STAT(YELLOWALIVE, int)
+REGISTER_STAT(PINKALIVE, int)
 
 // domination
-enum {
-    STAT_DOM_TOTAL_PPS = STAT_LAST_MAIN,
-    STAT_DOM_PPS_RED,
-    STAT_DOM_PPS_BLUE,
-    STAT_DOM_PPS_YELLOW,
-    STAT_DOM_PPS_PINK,
-};
+REGISTER_STAT(DOM_TOTAL_PPS, float)
+REGISTER_STAT(DOM_PPS_RED, float)
+REGISTER_STAT(DOM_PPS_BLUE, float)
+REGISTER_STAT(DOM_PPS_YELLOW, float)
+REGISTER_STAT(DOM_PPS_PINK, float)
 
-// vip
-enum {
-    STAT_VIP = STAT_LAST_MAIN,
-    STAT_VIP_RED,
-    STAT_VIP_BLUE,
-    STAT_VIP_YELLOW,
-    STAT_VIP_PINK,
-};
+REGISTER_STAT(TELEPORT_MAXSPEED, float, autocvar_g_teleport_maxspeed)
+REGISTER_STAT(TELEPORT_TELEFRAG_AVOID, int, autocvar_g_telefrags_avoid)
 
-// key hunt
-enum {
-    STAT_KH_REDKEY_TEAM = STAT_LAST_MAIN,
-    STAT_KH_BLUEKEY_TEAM,
-    STAT_KH_YELLOWKEY_TEAM,
-    STAT_KH_PINKKEY_TEAM,
-};
+#ifdef SVQC
+#include "movetypes/movetypes.qh"
+#endif
+
+REGISTER_STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, float)
+REGISTER_STAT(MOVEVARS_AIRCONTROL_PENALTY, float)
+REGISTER_STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, float)
+REGISTER_STAT(MOVEVARS_AIRSTRAFEACCEL_QW, float)
+REGISTER_STAT(MOVEVARS_AIRCONTROL_POWER, float)
+noref bool autocvar_sv_gameplayfix_nogravityonground;
+REGISTER_STAT(MOVEFLAGS, int, MOVEFLAG_VALID
+                              | (autocvar_sv_gameplayfix_q2airaccelerate ? MOVEFLAG_Q2AIRACCELERATE : 0)
+                              | (autocvar_sv_gameplayfix_nogravityonground ? MOVEFLAG_NOGRAVITYONGROUND : 0)
+                              | (autocvar_sv_gameplayfix_gravityunaffectedbyticrate ? MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE : 0))
 
-#define ASSERT_LESS(name, var, const) noref int name[(const - var + 1)];
-ASSERT_LESS(stat_limit, STAT_LAST, 220)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_ACCEL, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, float)
+REGISTER_STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, float)
 
-const int STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR     = 220;
-const int STAT_MOVEVARS_AIRCONTROL_PENALTY            = 221;
-const int STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW           = 222;
-const int STAT_MOVEVARS_AIRSTRAFEACCEL_QW             = 223;
-const int STAT_MOVEVARS_AIRCONTROL_POWER              = 224;
-const int STAT_MOVEFLAGS                              = 225;
-const int STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL   = 226;
-const int STAT_MOVEVARS_WARSOWBUNNY_ACCEL             = 227;
-const int STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED          = 228;
-const int STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL         = 229;
-const int STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO   = 230;
-const int STAT_MOVEVARS_AIRSTOPACCELERATE             = 231;
-const int STAT_MOVEVARS_AIRSTRAFEACCELERATE           = 232;
-const int STAT_MOVEVARS_MAXAIRSTRAFESPEED             = 233;
-const int STAT_MOVEVARS_AIRCONTROL                    = 234;
-// -Wdouble-declaration
-// const int STAT_FRAGLIMIT                              = 235;
-// -Wdouble-declaration
-// const int STAT_TIMELIMIT                              = 236;
-const int STAT_MOVEVARS_WALLFRICTION                  = 237;
-const int STAT_MOVEVARS_FRICTION                      = 238;
-const int STAT_MOVEVARS_WATERFRICTION                 = 239;
-// -Wdouble-declaration
-// const int STAT_MOVEVARS_TICRATE                       = 240;
-// -Wdouble-declaration
-// const int STAT_MOVEVARS_TIMESCALE                     = 241;
-// -Wdouble-declaration
-// const int STAT_MOVEVARS_GRAVITY                       = 242;
-const int STAT_MOVEVARS_STOPSPEED                     = 243;
-const int STAT_MOVEVARS_MAXSPEED                      = 244;
-const int STAT_MOVEVARS_SPECTATORMAXSPEED             = 245;
-const int STAT_MOVEVARS_ACCELERATE                    = 246;
-const int STAT_MOVEVARS_AIRACCELERATE                 = 247;
-const int STAT_MOVEVARS_WATERACCELERATE               = 248;
-const int STAT_MOVEVARS_ENTGRAVITY                    = 249;
-const int STAT_MOVEVARS_JUMPVELOCITY                  = 250;
-const int STAT_MOVEVARS_EDGEFRICTION                  = 251;
-const int STAT_MOVEVARS_MAXAIRSPEED                   = 252;
-const int STAT_MOVEVARS_STEPHEIGHT                    = 253;
-const int STAT_MOVEVARS_AIRACCEL_QW                   = 254;
-const int STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION    = 255;
+REGISTER_STAT(MOVEVARS_AIRSTOPACCELERATE, float)
+REGISTER_STAT(MOVEVARS_AIRSTRAFEACCELERATE, float)
+REGISTER_STAT(MOVEVARS_MAXAIRSTRAFESPEED, float)
+REGISTER_STAT(MOVEVARS_AIRCONTROL, float)
+REGISTER_STAT(FRAGLIMIT, float, autocvar_fraglimit)
+REGISTER_STAT(TIMELIMIT, float, autocvar_timelimit)
+#ifdef SVQC
+float autocvar_sv_wallfriction;
+#endif
+REGISTER_STAT(MOVEVARS_WALLFRICTION, int, autocvar_sv_wallfriction)
+REGISTER_STAT(MOVEVARS_TICRATE, float, autocvar_sys_ticrate)
+REGISTER_STAT(MOVEVARS_TIMESCALE, float, autocvar_slowmo)
+REGISTER_STAT(MOVEVARS_GRAVITY, float, autocvar_sv_gravity)
+REGISTER_STAT(MOVEVARS_STOPSPEED, float)
+REGISTER_STAT(MOVEVARS_MAXSPEED, float)
+REGISTER_STAT(MOVEVARS_ACCELERATE, float)
+REGISTER_STAT(MOVEVARS_AIRACCELERATE, float)
+.float gravity;
+// FIXME: Was 0 on server, 1 on client. Still want that?
+REGISTER_STAT(MOVEVARS_ENTGRAVITY, float, (this.gravity) ? this.gravity : 1)
+REGISTER_STAT(MOVEVARS_JUMPVELOCITY, float)
+REGISTER_STAT(MOVEVARS_MAXAIRSPEED, float)
+REGISTER_STAT(MOVEVARS_STEPHEIGHT, float, autocvar_sv_stepheight)
+REGISTER_STAT(MOVEVARS_AIRACCEL_QW, float)
+REGISTER_STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, float)
 #endif
index 87496b217649b97e07041cb78ab5350f1e9be4aa..35a2ff8f71529991254240a5f695757a3a21f4df 100644 (file)
@@ -643,7 +643,7 @@ float door_send(entity to, float sf)
 
                WriteString(MSG_ENTITY, self.model);
 
-               trigger_common_write(true);
+               trigger_common_write(self, true);
 
                WriteCoord(MSG_ENTITY, self.pos1_x);
                WriteCoord(MSG_ENTITY, self.pos1_y);
index 0ddf08eef07cb0585143f276a06c8b5fb139ce0f..bcf994ff4e42de7b845ab1c319592ef6d649980d 100644 (file)
@@ -8,10 +8,6 @@ void func_ladder_touch()
        if(IS_VEHICLE(other))
                return;
 #endif
-#ifdef CSQC
-       if(other.classname != "csqcmodel")
-               return;
-#endif
 
        EXACTTRIGGER_TOUCH;
 
@@ -20,69 +16,67 @@ void func_ladder_touch()
 }
 
 #ifdef SVQC
-bool func_ladder_send(entity this, entity to, float sf)
-{
+bool func_ladder_send(entity to, int sf)
+{SELFPARAM();
        WriteHeader(MSG_ENTITY, ENT_CLIENT_LADDER);
 
        WriteString(MSG_ENTITY, self.classname);
        WriteByte(MSG_ENTITY, self.skin);
-       WriteByte(MSG_ENTITY, self.speed);
-       WriteString(MSG_ENTITY, self.mdl);
+       WriteCoord(MSG_ENTITY, self.speed);
 
-       trigger_common_write(false);
+       trigger_common_write(self, false);
 
        return true;
 }
 
 void func_ladder_link()
 {
-       //self.SendEntity = func_ladder_send;
-       //self.SendFlags = 0xFFFFFF;
+       self.SendEntity = func_ladder_send;
+       self.SendFlags = 0xFFFFFF;
        //self.model = "null";
 }
 
-spawnfunc(func_ladder)
+void func_ladder_init()
 {
-       self.mdl = self.model;
-       EXACTTRIGGER_INIT;
        self.touch = func_ladder_touch;
 
+       trigger_init(self);
        func_ladder_link();
 }
 
-spawnfunc(func_water)
+spawnfunc(func_ladder)
 {
-       self.mdl = self.model;
-       EXACTTRIGGER_INIT;
-       self.touch = func_ladder_touch;
+       func_ladder_init();
+}
 
-       func_ladder_link();
+spawnfunc(func_water)
+{
+       func_ladder_init();
 }
 
 #elif defined(CSQC)
 .float speed;
 
+void func_ladder_remove()
+{
+       if(self.classname) { strunzone(self.classname); }
+       self.classname = string_null;
+}
+
 NET_HANDLE(ENT_CLIENT_LADDER, bool isnew)
 {
        self.classname = strzone(ReadString());
        self.skin = ReadByte();
-       self.speed = ReadByte();
-       self.model = strzone(ReadString());
+       self.speed = ReadCoord();
 
        trigger_common_read(false);
 
-       return = true;
-
-       self.mins = self.maxs = '0 0 0';
-
        self.solid = SOLID_TRIGGER;
-       self.draw = trigger_draw_generic;
-       self.trigger_touch = func_ladder_touch;
+       self.move_touch = func_ladder_touch;
        self.drawmask = MASK_NORMAL;
        self.move_time = time;
-       self.entremove = trigger_remove_generic;
+       self.entremove = func_ladder_remove;
 
-       //precache_model(self.mdl);
-       EXACTTRIGGER_INIT;
+       return true;
 }
 #endif
index 9e98d12ba25416508e57e06d22c865080fc35594..ea546164ce71fb0589b03f12f8fea3962c82f214 100644 (file)
@@ -23,7 +23,7 @@ float plat_send(entity to, float sf)
 
                WriteString(MSG_ENTITY, self.model);
 
-               trigger_common_write(true);
+               trigger_common_write(self, true);
 
                WriteCoord(MSG_ENTITY, self.pos1_x);
                WriteCoord(MSG_ENTITY, self.pos1_y);
index 80350e743b94ba07c27abf54cb3eb7c0f0bd47fb..e02b917d1cc118cfc73c0cffea72f60790f3ee29 100644 (file)
@@ -117,7 +117,7 @@ float train_send(entity to, float sf)
 
                WriteString(MSG_ENTITY, self.model);
 
-               trigger_common_write(true);
+               trigger_common_write(self, true);
 
                WriteString(MSG_ENTITY, self.curvetarget);
 
index 00752cfa59c5faa92a39756d31272ceec224e03a..5a367308e4d0ebd0bd2c51b448b71b189a2e6db1 100644 (file)
@@ -1,5 +1,35 @@
+REGISTER_NET_LINKED(ENT_CLIENT_TELEPORT_DEST)
+
 #ifdef SVQC
 
+bool teleport_dest_send(entity this, entity to, int sf)
+{
+       WriteHeader(MSG_ENTITY, ENT_CLIENT_TELEPORT_DEST);
+       WriteByte(MSG_ENTITY, sf);
+
+       if(sf & 1)
+       {
+               WriteByte(MSG_ENTITY, this.cnt);
+               WriteCoord(MSG_ENTITY, this.speed);
+               WriteString(MSG_ENTITY, this.targetname);
+               WriteCoord(MSG_ENTITY, this.origin_x);
+               WriteCoord(MSG_ENTITY, this.origin_y);
+               WriteCoord(MSG_ENTITY, this.origin_z);
+
+               WriteAngle(MSG_ENTITY, this.mangle_x);
+               WriteAngle(MSG_ENTITY, this.mangle_y);
+               WriteAngle(MSG_ENTITY, this.mangle_z);
+       }
+
+       return true;
+}
+
+void teleport_dest_link()
+{SELFPARAM();
+       Net_LinkEntity(self, false, 0, teleport_dest_send);
+       //self.SendFlags |= 1; // update
+}
+
 spawnfunc(info_teleport_destination)
 {
        self.classname = "info_teleport_destination";
@@ -15,6 +45,8 @@ spawnfunc(info_teleport_destination)
        }
        else
                objerror ("^3Teleport destination without a targetname");
+
+       teleport_dest_link();
 }
 
 spawnfunc(misc_teleporter_dest)
@@ -27,4 +59,44 @@ spawnfunc(target_teleporter)
        spawnfunc_info_teleport_destination(this);
 }
 
+#elif defined(CSQC)
+
+void teleport_dest_remove()
+{SELFPARAM();
+       //if(self.classname)
+               //strunzone(self.classname);
+       //self.classname = string_null;
+
+       if(self.targetname)
+               strunzone(self.targetname);
+       self.targetname = string_null;
+}
+
+NET_HANDLE(ENT_CLIENT_TELEPORT_DEST, bool isnew)
+{
+       int sf = ReadByte();
+
+       if(sf & 1)
+       {
+               self.classname = "info_teleport_destination";
+               self.cnt = ReadByte();
+               self.speed = ReadCoord();
+               self.targetname = strzone(ReadString());
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+
+               self.mangle_x = ReadAngle();
+               self.mangle_y = ReadAngle();
+               self.mangle_z = ReadAngle();
+
+               setorigin(self, self.origin);
+
+               self.drawmask = MASK_NORMAL;
+               self.entremove = teleport_dest_remove;
+       }
+
+       return = true;
+}
+
 #endif
index fa68533f4afcb594a6d727389fc65e4d23c78482..19ccde9dca08ec764fa86fd5a0a788e915642d36 100644 (file)
@@ -47,15 +47,6 @@ void SUB_VanishOrRemove (entity ent);
 .vector destvec;
 .vector destvec2;
 
-// player animation state
-.float animstate_startframe;
-.float animstate_numframes;
-.float animstate_framerate;
-.float animstate_starttime;
-.float animstate_endtime;
-.float animstate_override;
-.float animstate_looping;
-
 .float delay;
 .float wait;
 .float lip;
index 1f0c00e5e8e2d36211cffe95d5bd1b26390b7771..1f4d0a664217b49ce3d6a25d3a9ac21100074c62 100644 (file)
     #include "../../server/anticheat.qh"
 #endif
 
-#ifdef SVQC
-
 float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax)
 {
-       if (IS_PLAYER(player) && player.health >= 1)
+       if (IS_PLAYER(player) && !PHYS_DEAD(player))
        {
                TDEATHLOOP(org)
                {
+               #ifdef SVQC
                        if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
+               #endif
                                if(IS_PLAYER(head))
-                                       if(head.health >= 1)
+                                       if(!PHYS_DEAD(head))
                                                return 1;
                }
        }
        return 0;
 }
 
+#ifdef SVQC
+
+void trigger_teleport_link(entity this);
+
 void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax)
 {
        TDEATHLOOP(player.origin)
@@ -61,6 +65,8 @@ void spawn_tdeath(vector v0, entity e, vector v)
        tdeath(e, e, e, '0 0 0', '0 0 0');
 }
 
+#endif
+
 void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
 {SELFPARAM();
        entity telefragger;
@@ -73,6 +79,7 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle
 
        makevectors (to_angles);
 
+#ifdef SVQC
        if(player.teleportable == TELEPORT_NORMAL) // don't play sounds or show particles for anything that isn't a player, maybe change later to block only observers
        {
                if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
@@ -87,9 +94,11 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle
                        self.pushltime = time + 0.2;
                }
        }
+#endif
 
        // Relocate the player
        // assuming to allows PL_MIN to PL_MAX box and some more
+#ifdef SVQC
        from = player.origin;
        setorigin (player, to);
        player.oldorigin = to; // don't undo the teleport by unsticking
@@ -101,7 +110,22 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle
        makevectors(player.angles);
        Reset_ArcBeam(player, v_forward);
        UpdateCSQCProjectileAfterTeleport(player);
+#elif defined(CSQC)
+       from = player.move_origin;
+       player.move_origin = to;
+       player.move_angles = to_angles;
+       player.move_velocity = to_velocity;
+       player.move_flags &= ~FL_ONGROUND;
+       player.iflags |= IFLAG_TELEPORTED | IFLAG_V_ANGLE | IFLAG_ANGLES;
+       player.csqcmodel_teleported = 1;
+       player.v_angle = to_angles;
+       setproperty(VF_ANGLES, player.move_angles);
+       setproperty(VF_CL_VIEWANGLES, player.move_angles);
+
+       makevectors(player.move_angles);
+#endif
 
+#ifdef SVQC
        if(IS_PLAYER(player))
        {
                if(tflags & TELEPORT_FLAG_TDEATH)
@@ -129,6 +153,7 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle
 
                player.lastteleporttime = time;
        }
+#endif
 }
 
 entity Simple_TeleportPlayer(entity teleporter, entity player)
@@ -148,9 +173,13 @@ entity Simple_TeleportPlayer(entity teleporter, entity player)
                for(e = world; (e = find(e, targetname, teleporter.target)); )
                {
                        p = 1;
-                       if(autocvar_g_telefrags_avoid)
+                       if(STAT(TELEPORT_TELEFRAG_AVOID, player))
                        {
+                       #ifdef SVQC
                                locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+                       #elif defined(CSQC)
+                               locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+                       #endif
                                if(check_tdeath(player, locout, '0 0 0', '0 0 0'))
                                        p = 0;
                        }
@@ -159,37 +188,60 @@ entity Simple_TeleportPlayer(entity teleporter, entity player)
                e = RandomSelection_chosen_ent;
        }
 
+#ifdef SVQC
        if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
+#elif defined(CSQC)
+       if(!e) { LOG_INFO("Teleport destination could not be found from CSQC.\n"); }
+#endif
 
        makevectors(e.mangle);
 
+#ifdef SVQC
        if(e.speed)
                if(vlen(player.velocity) > e.speed)
                        player.velocity = normalize(player.velocity) * max(0, e.speed);
+#elif defined(CSQC)
+       if(e.speed)
+               if(vlen(player.move_velocity) > e.speed)
+                       player.move_velocity = normalize(player.move_velocity) * max(0, e.speed);
+#endif
 
-       if(autocvar_g_teleport_maxspeed)
-               if(vlen(player.velocity) > autocvar_g_teleport_maxspeed)
-                       player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed);
+#ifdef SVQC
+       if(STAT(TELEPORT_MAXSPEED, player))
+               if(vlen(player.velocity) > STAT(TELEPORT_MAXSPEED, player))
+                       player.velocity = normalize(player.velocity) * max(0, STAT(TELEPORT_MAXSPEED, player));
+#elif defined(CSQC)
+       if(STAT(TELEPORT_MAXSPEED, player))
+               if(vlen(player.move_velocity) > STAT(TELEPORT_MAXSPEED, player))
+                       player.move_velocity = normalize(player.move_velocity) * max(0, STAT(TELEPORT_MAXSPEED, player));
+#endif
 
+#ifdef SVQC
        locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+
        TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+#elif defined(CSQC)
+       locout = e.origin + '0 0 1' * (1 - player.mins.z - 24);
+
+       TeleportPlayer(teleporter, player, locout, e.mangle, v_forward * vlen(player.move_velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
+#endif
 
        return e;
 }
 
-void teleport_findtarget ()
-{SELFPARAM();
+void teleport_findtarget()
+{
+       int n = 0;
        entity e;
-       float n;
-
-       n = 0;
        for(e = world; (e = find(e, targetname, self.target)); )
        {
                ++n;
+#ifdef SVQC
                if(e.movetype == MOVETYPE_NONE)
                        waypoint_spawnforteleporter(self, e.origin, 0);
                if(e.classname != "info_teleport_destination")
                        LOG_INFO("^3MAPPER ERROR: teleporter does target an invalid teleport destination entity. Angles will not work.\n");
+#endif
        }
 
        if(n == 0)
@@ -210,7 +262,13 @@ void teleport_findtarget ()
        }
 
        // now enable touch
+#ifdef SVQC
        self.touch = Teleport_Touch;
+
+       trigger_teleport_link(self);
+#elif defined(CSQC)
+       self.move_touch = Teleport_Touch;
+#endif
 }
 
 entity Teleport_Find(vector mi, vector ma)
@@ -224,26 +282,33 @@ entity Teleport_Find(vector mi, vector ma)
 
 void WarpZone_PostTeleportPlayer_Callback(entity pl)
 {SELFPARAM();
+#ifdef SVQC
        makevectors(pl.angles);
        Reset_ArcBeam(pl, v_forward);
        UpdateCSQCProjectileAfterTeleport(pl);
        {
                WITH(entity, self, pl, anticheat_fixangle());
        }
+#endif
        // "disown" projectiles after teleport
        if(pl.owner)
        if(pl.owner == pl.realowner)
        {
+       #ifdef SVQC
                if(!(pl.flags & FL_PROJECTILE))
+       #elif defined(CSQC)
+               if(!(pl.move_flags & BIT(15))) // FL_PROJECTILE
+       #endif
                        LOG_INFO("A non-projectile got through a warpzone and its owner cleared. It's a ", pl.classname, ".\n");
                pl.owner = world;
        }
        if(IS_PLAYER(pl))
        {
                // reset tracking of oldvelocity for impact damage (sudden velocity changes)
+       #ifdef SVQC
                pl.oldvelocity = pl.velocity;
+       #endif
                // reset teleport time tracking too (or multijump can cause insane speeds)
                pl.lastteleporttime = time;
        }
 }
-#endif
index 01e738e43de17e3be53160ea1b91866c5cfb14cb..0e9e23572f323df37678c4bb9eacd98a9b85c361 100644 (file)
@@ -1,6 +1,33 @@
 #ifndef T_TELEPORTERS_H
 #define T_TELEPORTERS_H
 
+.entity pusher;
+const float TELEPORT_FLAG_SOUND = 1;
+const float TELEPORT_FLAG_PARTICLES = 2;
+const float TELEPORT_FLAG_TDEATH = 4;
+const float TELEPORT_FLAG_FORCE_TDEATH = 8;
+
+#define TELEPORT_FLAGS_WARPZONE   0
+#define TELEPORT_FLAGS_PORTAL     (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
+#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
+
+// types for .teleportable entity setting
+const float TELEPORT_NORMAL = 1; // play sounds/effects etc
+const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
+
+entity Simple_TeleportPlayer(entity teleporter, entity player);
+
+void Teleport_Touch ();
+
+void teleport_findtarget();
+
+entity Teleport_Find(vector mi, vector ma);
+
+void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
+
+entity teleport_first;
+.entity teleport_next;
+
 #ifdef SVQC
 
 void trigger_teleport_use();
@@ -27,42 +54,43 @@ void trigger_teleport_use();
                        if(head.takedamage) \
                                if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
 
-
 float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax);
 float tdeath_hit;
 void tdeath(entity player, entity teleporter, entity telefragger, vector telefragmin, vector telefragmax);
 
 void spawn_tdeath(vector v0, entity e, vector v);
 
-.entity pusher;
-const float TELEPORT_FLAG_SOUND = 1;
-const float TELEPORT_FLAG_PARTICLES = 2;
-const float TELEPORT_FLAG_TDEATH = 4;
-const float TELEPORT_FLAG_FORCE_TDEATH = 8;
-
-#define TELEPORT_FLAGS_WARPZONE   0
-#define TELEPORT_FLAGS_PORTAL     (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
-#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
-
-// types for .teleportable entity setting
-const float TELEPORT_NORMAL = 1; // play sounds/effects etc
-const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
-
 void Reset_ArcBeam(entity player, vector forward);
-void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags);
-
-entity Simple_TeleportPlayer(entity teleporter, entity player);
-
-void Teleport_Touch ();
 
-void teleport_findtarget ();
+#endif
 
-entity Teleport_Find(vector mi, vector ma);
+void WarpZone_PostTeleportPlayer_Callback(entity pl);
 
-entity teleport_first;
-.entity teleport_next;
+#ifdef CSQC
+.entity realowner;
+.float lastteleporttime;
 
-void WarpZone_PostTeleportPlayer_Callback(entity pl);
+#define TDEATHLOOP(o) \
+       entity head; \
+       vector deathmin; \
+       vector deathmax; \
+       float deathradius; \
+       deathmin = (o) + player.mins; \
+       deathmax = (o) + player.maxs; \
+       if(telefragmin != telefragmax) \
+       { \
+               if(deathmin.x > telefragmin.x) deathmin.x = telefragmin.x; \
+               if(deathmin.y > telefragmin.y) deathmin.y = telefragmin.y; \
+               if(deathmin.z > telefragmin.z) deathmin.z = telefragmin.z; \
+               if(deathmax.x < telefragmax.x) deathmax.x = telefragmax.x; \
+               if(deathmax.y < telefragmax.y) deathmax.y = telefragmax.y; \
+               if(deathmax.z < telefragmax.z) deathmax.z = telefragmax.z; \
+       } \
+       deathradius = max(vlen(deathmin), vlen(deathmax)); \
+       for(head = findradius(o, deathradius); head; head = head.chain) \
+               if(head != player) \
+                       if(head.isplayermodel) \
+                               if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
 #endif
 
 #endif
index 77c491c356b58647ad0c34c2d467b2e138d92c4b..c2b59a3e0b40b348b25b8ca6f09f8b61955e54e5 100644 (file)
@@ -21,7 +21,11 @@ void trigger_impulse_touch1()
                return;
        }
 
+#ifdef SVQC
        str = min(self.radius, vlen(self.origin - other.origin));
+#elif defined(CSQC)
+       str = min(self.radius, vlen(self.origin - other.move_origin));
+#endif
 
        if(self.falloff == 1)
                str = (str / self.radius) * self.strength;
@@ -37,18 +41,35 @@ void trigger_impulse_touch1()
 
        if(self.spawnflags & 64)
        {
+#ifdef SVQC
                float addspeed = str - other.velocity * normalize(targ.origin - self.origin);
                if (addspeed > 0)
                {
                        float accelspeed = min(8 * pushdeltatime * str, addspeed);
                        other.velocity += accelspeed * normalize(targ.origin - self.origin);
                }
+#elif defined(CSQC)
+               float addspeed = str - other.move_velocity * normalize(targ.origin - self.origin);
+               if (addspeed > 0)
+               {
+                       float accelspeed = min(8 * pushdeltatime * str, addspeed);
+                       other.move_velocity += accelspeed * normalize(targ.origin - self.origin);
+               }
+#endif
        }
        else
+#ifdef SVQC
                other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
-       other.flags &= ~FL_ONGROUND;
+#elif defined(CSQC)
+               other.move_velocity = other.move_velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
+#endif
+
 #ifdef SVQC
+       UNSET_ONGROUND(other);
+
        UpdateCSQCProjectile(other);
+#elif defined(CSQC)
+       other.move_flags &= ~FL_ONGROUND;
 #endif
 }
 
@@ -71,9 +92,12 @@ void trigger_impulse_touch2()
        if(!pushdeltatime) return;
 
        // div0: ticrate independent, 1 = identity (not 20)
-       other.velocity = other.velocity * pow(self.strength, pushdeltatime);
 #ifdef SVQC
+       other.velocity = other.velocity * pow(self.strength, pushdeltatime);
+
        UpdateCSQCProjectile(other);
+#elif defined(CSQC)
+       other.move_velocity = other.move_velocity * pow(self.strength, pushdeltatime);
 #endif
 }
 
@@ -98,7 +122,11 @@ void trigger_impulse_touch3()
 
        setsize(self, '-1 -1 -1' * self.radius,'1 1 1' * self.radius);
 
+#ifdef SVQC
        str = min(self.radius, vlen(self.origin - other.origin));
+#elif defined(CSQC)
+       str = min(self.radius, vlen(self.origin - other.move_origin));
+#endif
 
        if(self.falloff == 1)
                str = (1 - str / self.radius) * self.strength; // 1 in the inside
@@ -107,9 +135,12 @@ void trigger_impulse_touch3()
        else
                str = self.strength;
 
-       other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
 #ifdef SVQC
+       other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
+
        UpdateCSQCProjectile(other);
+#elif defined(CSQC)
+       other.move_velocity = other.move_velocity + normalize(other.move_origin - self.origin) * str * pushdeltatime;
 #endif
 }
 
@@ -133,30 +164,32 @@ Use a brush textured with common/origin in the trigger entity to determine the o
 in directional and sperical mode. For damper/accelerator mode this is not nessesary (and has no effect).
 */
 #ifdef SVQC
-bool trigger_impulse_send(entity to, int sf)
-{SELFPARAM();
+bool trigger_impulse_send(entity this, entity to, int sf)
+{
        WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
 
-       WriteCoord(MSG_ENTITY, self.radius);
-       WriteCoord(MSG_ENTITY, self.strength);
-       WriteByte(MSG_ENTITY, self.falloff);
-       WriteByte(MSG_ENTITY, self.active);
+       WriteInt24_t(MSG_ENTITY, this.spawnflags);
+       WriteCoord(MSG_ENTITY, this.radius);
+       WriteCoord(MSG_ENTITY, this.strength);
+       WriteByte(MSG_ENTITY, this.falloff);
+       WriteByte(MSG_ENTITY, this.active);
 
-       trigger_common_write(true);
+       trigger_common_write(this, true);
 
        return true;
 }
 
 void trigger_impulse_link()
 {
-       //Net_LinkEntity(self, 0, false, trigger_impulse_send);
+       trigger_link(self, trigger_impulse_send);
 }
 
 spawnfunc(trigger_impulse)
 {
        self.active = ACTIVE_ACTIVE;
 
-       EXACTTRIGGER_INIT;
+       trigger_init(self);
+
        if(self.radius)
        {
                if(!self.strength) self.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
@@ -184,6 +217,7 @@ spawnfunc(trigger_impulse)
 #elif defined(CSQC)
 NET_HANDLE(ENT_CLIENT_TRIGGER_IMPULSE, bool isnew)
 {
+       self.spawnflags = ReadInt24_t();
        self.radius = ReadCoord();
        self.strength = ReadCoord();
        self.falloff = ReadByte();
@@ -195,12 +229,12 @@ NET_HANDLE(ENT_CLIENT_TRIGGER_IMPULSE, bool isnew)
        self.classname = "trigger_impulse";
        self.solid = SOLID_TRIGGER;
        self.entremove = trigger_remove_generic;
-       self.draw = trigger_draw_generic;
+       //self.draw = trigger_draw_generic;
        self.drawmask = MASK_NORMAL;
        self.move_time = time;
 
-       if(self.radius) { self.trigger_touch = trigger_impulse_touch3; }
-       else if(self.target) { self.trigger_touch = trigger_impulse_touch1; }
-       else { self.trigger_touch = trigger_impulse_touch2; }
+       if(self.radius) { self.move_touch = trigger_impulse_touch3; }
+       else if(self.target) { self.move_touch = trigger_impulse_touch1; }
+       else { self.move_touch = trigger_impulse_touch2; }
 }
 #endif
index 8c521e7dd899c1af1319585faf049e8b778c9422..cdd383e536216af459824fbfd2be574b3d33d848 100644 (file)
@@ -37,7 +37,7 @@ vector trigger_push_calculatevelocity(vector org, entity tgt, float ht)
 
        torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
 
-       grav = PHYS_GRAVITY;
+       grav = PHYS_GRAVITY(other);
        if(PHYS_ENTGRAVITY(other))
                grav *= PHYS_ENTGRAVITY(other);
 
@@ -170,9 +170,11 @@ void trigger_push_touch()
                other.move_velocity = other.velocity;
        }
 
+#ifdef SVQC
        UNSET_ONGROUND(other);
-
+#elif defined(CSQC)
        other.move_flags &= ~FL_ONGROUND;
+#endif
 
 #ifdef SVQC
        if (IS_PLAYER(other))
@@ -318,26 +320,16 @@ void trigger_push_findtarget()
 }
 
 #ifdef SVQC
-float trigger_push_send(entity to, float sf)
-{SELFPARAM();
+float trigger_push_send(entity this, entity to, float sf)
+{
        WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_PUSH);
-       WriteByte(MSG_ENTITY, sf);
-
-       if(sf & 1)
-       {
-               WriteByte(MSG_ENTITY, self.team);
-               WriteInt24_t(MSG_ENTITY, self.spawnflags);
-               WriteByte(MSG_ENTITY, self.active);
-               WriteByte(MSG_ENTITY, self.height);
 
-               trigger_common_write(true);
-       }
+       WriteByte(MSG_ENTITY, self.team);
+       WriteInt24_t(MSG_ENTITY, self.spawnflags);
+       WriteByte(MSG_ENTITY, self.active);
+       WriteCoord(MSG_ENTITY, self.height);
 
-       if(sf & 2)
-       {
-               WriteByte(MSG_ENTITY, self.team);
-               WriteByte(MSG_ENTITY, self.active);
-       }
+       trigger_common_write(self, true);
 
        return true;
 }
@@ -349,10 +341,9 @@ void trigger_push_updatelink()
 
 void trigger_push_link()
 {
-       //Net_LinkEntity(self, false, 0, trigger_push_send);
+       trigger_link(self, trigger_push_send);
 }
-#endif
-#ifdef SVQC
+
 /*
  * ENTITY PARAMETERS:
  *
@@ -369,7 +360,7 @@ spawnfunc(trigger_push)
 {
        SetMovedir(self);
 
-       EXACTTRIGGER_INIT;
+       trigger_init(self);
 
        self.active = ACTIVE_ACTIVE;
        self.use = trigger_push_use;
@@ -399,12 +390,17 @@ bool target_push_send(entity this, entity to, float sf)
        WriteCoord(MSG_ENTITY, self.origin_y);
        WriteCoord(MSG_ENTITY, self.origin_z);
 
+       WriteAngle(MSG_ENTITY, self.angles_x);
+       WriteAngle(MSG_ENTITY, self.angles_y);
+       WriteAngle(MSG_ENTITY, self.angles_z);
+
        return true;
 }
 
 void target_push_link()
 {SELFPARAM();
-       //Net_LinkEntity(self, false, 0, target_push_send);
+       BITSET_ASSIGN(self.effects, EF_NODEPTHTEST);
+       Net_LinkEntity(self, false, 0, target_push_send);
        //self.SendFlags |= 1; // update
 }
 
@@ -412,38 +408,28 @@ spawnfunc(target_push) { target_push_link(); }
 spawnfunc(info_notnull) { target_push_link(); }
 spawnfunc(target_position) { make_pure(this); target_push_link(); }
 
-#endif
-
-#ifdef CSQC
+#elif defined(CSQC)
 
 NET_HANDLE(ENT_CLIENT_TRIGGER_PUSH, bool isnew)
 {
-       float sf = ReadByte();
+       make_pure(this);
 
-       if(sf & 1)
-       {
-               self.classname = "jumppad";
-               int mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
-               self.spawnflags = ReadInt24_t();
-               self.active = ReadByte();
-               self.height = ReadByte();
-
-               trigger_common_read(true);
-
-               self.entremove = trigger_remove_generic;
-               self.solid = SOLID_TRIGGER;
-               self.draw = trigger_draw_generic;
-               self.trigger_touch = trigger_push_touch;
-               self.drawmask = MASK_NORMAL;
-               self.move_time = time;
-               trigger_push_findtarget();
-       }
+       self.classname = "jumppad";
+       int mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
+       self.spawnflags = ReadInt24_t();
+       self.active = ReadByte();
+       self.height = ReadCoord();
+
+       trigger_common_read(true);
+
+       self.entremove = trigger_remove_generic;
+       self.solid = SOLID_TRIGGER;
+       //self.draw = trigger_draw_generic;
+       self.move_touch = trigger_push_touch;
+       self.drawmask = MASK_NORMAL;
+       self.move_time = time;
+       defer(self, 0.25, trigger_push_findtarget);
 
-       if(sf & 2)
-       {
-               self.team = ReadByte();
-               self.active = ReadByte();
-       }
        return true;
 }
 
@@ -460,6 +446,7 @@ void target_push_remove()
 
 NET_HANDLE(ENT_CLIENT_TARGET_PUSH, bool isnew)
 {
+       make_pure(this);
        self.classname = "push_target";
        self.cnt = ReadByte();
        self.targetname = strzone(ReadString());
@@ -467,6 +454,10 @@ NET_HANDLE(ENT_CLIENT_TARGET_PUSH, bool isnew)
        self.origin_y = ReadCoord();
        self.origin_z = ReadCoord();
 
+       self.angles_x = ReadAngle();
+       self.angles_y = ReadAngle();
+       self.angles_z = ReadAngle();
+
        return = true;
 
        setorigin(self, self.origin);
index 98b121d6eebc9eca44930c10f61ea0f442775b1a..b628eaf8250baa7e9591db4028d07673b4385176 100644 (file)
@@ -104,7 +104,7 @@ bool trigger_keylock_send(entity to, int sf)
        WriteInt24_t(MSG_ENTITY, self.itemkeys);
        WriteByte(MSG_ENTITY, self.height);
 
-       trigger_common_write(true);
+       trigger_common_write(self, true);
 
        return true;
 }
index c09da6b96563f883e8b5f7d0124b7ce6f48e953b..dace6045fb0c6a5dd40234adbabafd870cc32b52 100644 (file)
@@ -13,8 +13,8 @@ float secrets_total;
 float secrets_found;
 
 
-.float stat_secrets_total;
-.float stat_secrets_found;
+.float stat_secrets_total = _STAT(SECRETS_TOTAL);
+.float stat_secrets_found = _STAT(SECRETS_FOUND);
 
 /**
  * update secrets status.
index ae29a75342fa4fee0a6446a85cf41a5d48ca7e75..2a03db78da3dc507bb8602a11d36f0ed319276d2 100644 (file)
@@ -95,22 +95,22 @@ void swamp_touch()
 REGISTER_NET_LINKED(ENT_CLIENT_SWAMP)
 
 #ifdef SVQC
-float swamp_send(entity to, float sf)
-{SELFPARAM();
+float swamp_send(entity this, entity to, float sf)
+{
        WriteHeader(MSG_ENTITY, ENT_CLIENT_SWAMP);
 
-       WriteByte(MSG_ENTITY, self.dmg); // can probably get away with using a single byte here
-       WriteByte(MSG_ENTITY, self.swamp_slowdown);
-       WriteByte(MSG_ENTITY, self.swamp_interval);
+       WriteByte(MSG_ENTITY, this.dmg); // can probably get away with using a single byte here
+       WriteByte(MSG_ENTITY, this.swamp_slowdown);
+       WriteByte(MSG_ENTITY, this.swamp_interval);
 
-       trigger_common_write(false);
+       trigger_common_write(this, false);
 
        return true;
 }
 
 void swamp_link()
 {SELFPARAM();
-       Net_LinkEntity(self, false, 0, func_ladder_send);
+       trigger_link(self, swamp_send);
 }
 
 /*QUAKED spawnfunc_trigger_swamp (.5 .5 .5) ?
@@ -120,7 +120,7 @@ get slowd down and damaged
 spawnfunc(trigger_swamp)
 {
        // Init stuff
-       EXACTTRIGGER_INIT;
+       trigger_init(self);
        self.touch = swamp_touch;
 
        // Setup default keys, if missing
@@ -148,8 +148,7 @@ NET_HANDLE(ENT_CLIENT_SWAMP, bool isnew)
 
        self.classname = "trigger_swamp";
        self.solid = SOLID_TRIGGER;
-       self.draw = trigger_draw_generic;
-       self.trigger_touch = swamp_touch;
+       self.move_touch = swamp_touch;
        self.drawmask = MASK_NORMAL;
        self.move_time = time;
        self.entremove = trigger_remove_generic;
index 6522669200dee79b380f9c9b9d26bbe94c973c24..48b0341d33c832315133470715c668d844fd6b4c 100644 (file)
@@ -1,3 +1,5 @@
+REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_TELEPORT)
+
 #ifdef SVQC
 void trigger_teleport_use()
 {SELFPARAM();
@@ -7,14 +9,14 @@ void trigger_teleport_use()
        self.SendFlags |= SF_TRIGGER_UPDATE;
 #endif
 }
+#endif
 
 void Teleport_Touch ()
 {SELFPARAM();
-       string s;
-
        if (self.active != ACTIVE_ACTIVE)
                return;
 
+#ifdef SVQC
        if (!other.teleportable)
                return;
 
@@ -24,37 +26,61 @@ void Teleport_Touch ()
 
        if(IS_TURRET(other))
                return;
+#endif
 
-       if(other.deadflag != DEAD_NO)
+       if(PHYS_DEAD(other))
                return;
 
        if(self.team)
-               if(((self.spawnflags & 4) == 0) == (self.team != other.team))
+               if(((self.spawnflags & 4) == 0) == (DIFF_TEAM(this, other)))
                        return;
 
        EXACTTRIGGER_TOUCH;
 
+#ifdef SVQC
        if(IS_PLAYER(other))
                RemoveGrapplingHook(other);
+#endif
 
-       entity e = Simple_TeleportPlayer(self, other);
+       entity e;
+       e = Simple_TeleportPlayer(self, other);
 
+#ifdef SVQC
        activator = other;
-       s = self.target; self.target = string_null;
+       string s = self.target; self.target = string_null;
        SUB_UseTargets();
        if (!self.target) self.target = s;
 
        WITH(entity, self, e, SUB_UseTargets());
+#endif
+}
+
+#ifdef SVQC
+float trigger_teleport_send(entity this, entity to, float sf)
+{
+       WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_TELEPORT);
+
+       WriteByte(MSG_ENTITY, this.team);
+       WriteInt24_t(MSG_ENTITY, this.spawnflags);
+       WriteByte(MSG_ENTITY, this.active);
+       WriteCoord(MSG_ENTITY, this.speed);
+
+       trigger_common_write(this, true);
+
+       return true;
+}
+
+void trigger_teleport_link(entity this)
+{
+       trigger_link(this, trigger_teleport_send);
 }
 
 spawnfunc(trigger_teleport)
 {
        self.angles = '0 0 0';
 
-       EXACTTRIGGER_INIT;
-
        self.active = ACTIVE_ACTIVE;
-
+       trigger_init(self);
        self.use = trigger_teleport_use;
 
        // this must be called to spawn the teleport waypoints for bots
@@ -69,4 +95,29 @@ spawnfunc(trigger_teleport)
        self.teleport_next = teleport_first;
        teleport_first = self;
 }
+#elif defined(CSQC)
+NET_HANDLE(ENT_CLIENT_TRIGGER_TELEPORT, bool isnew)
+{
+       self.classname = "trigger_teleport";
+       int mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
+       self.spawnflags = ReadInt24_t();
+       self.active = ReadByte();
+       self.speed = ReadCoord();
+
+       trigger_common_read(true);
+
+       self.entremove = trigger_remove_generic;
+       self.solid = SOLID_TRIGGER;
+       //self.draw = trigger_draw_generic;
+       //self.move_touch = trigger_push_touch;
+       self.drawmask = MASK_NORMAL;
+       self.move_time = time;
+       defer(self, 0.25, teleport_findtarget);
+
+       self.teleport_next = teleport_first;
+       teleport_first = self;
+
+       return true;
+}
+
 #endif
index 41180dd2cc806b020a441b50f03cb2ff08f9f160..cd1d0260c01c8d2836f6e1fc369ae1208591e0a2 100644 (file)
@@ -21,69 +21,117 @@ void FixSize(entity e)
 }
 
 #ifdef SVQC
-void trigger_common_write(bool withtarget)
-{SELFPARAM();
-       WriteByte(MSG_ENTITY, self.warpzone_isboxy);
-       WriteByte(MSG_ENTITY, self.scale);
 
-       if(withtarget)
-       {
-               WriteString(MSG_ENTITY, self.target);
-               WriteString(MSG_ENTITY, self.target2);
-               WriteString(MSG_ENTITY, self.target3);
-               WriteString(MSG_ENTITY, self.target4);
-               WriteString(MSG_ENTITY, self.targetname);
-               WriteString(MSG_ENTITY, self.killtarget);
+void trigger_init(entity this)
+{
+       string m = this.model;
+       WITH(entity, self, this, WarpZoneLib_ExactTrigger_Init());
+       if(m != "")
+       {
+               precache_model(m);
+               _setmodel(this, m); // no precision needed
        }
+       setorigin(this, this.origin);
+       if(this.scale)
+               setsize(this, this.mins * this.scale, this.maxs * this.scale);
+       else
+               setsize(this, this.mins, this.maxs);
 
-       WriteCoord(MSG_ENTITY, self.origin_x);
-       WriteCoord(MSG_ENTITY, self.origin_y);
-       WriteCoord(MSG_ENTITY, self.origin_z);
+       BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
+}
 
-       WriteCoord(MSG_ENTITY, self.mins_x);
-       WriteCoord(MSG_ENTITY, self.mins_y);
-       WriteCoord(MSG_ENTITY, self.mins_z);
-       WriteCoord(MSG_ENTITY, self.maxs_x);
-       WriteCoord(MSG_ENTITY, self.maxs_y);
-       WriteCoord(MSG_ENTITY, self.maxs_z);
+void trigger_link(entity this, bool(entity this, entity to, int sendflags) sendfunc)
+{
+       this.SendEntity = SendEntity_self;
+       this.SendEntity3 = sendfunc;
+       this.SendFlags = 0xFFFFFF;
+}
 
-       WriteCoord(MSG_ENTITY, self.movedir_x);
-       WriteCoord(MSG_ENTITY, self.movedir_y);
-       WriteCoord(MSG_ENTITY, self.movedir_z);
+void trigger_common_write(entity this, bool withtarget)
+{
+       int f = 0;
+       if(this.warpzone_isboxy)
+               BITSET_ASSIGN(f, 1);
+       if(this.origin != '0 0 0')
+               BITSET_ASSIGN(f, 4);
+       WriteByte(MSG_ENTITY, f);
 
-       WriteCoord(MSG_ENTITY, self.angles_x);
-       WriteCoord(MSG_ENTITY, self.angles_y);
-       WriteCoord(MSG_ENTITY, self.angles_z);
+       if(withtarget)
+       {
+               WriteString(MSG_ENTITY, this.target);
+               WriteString(MSG_ENTITY, this.target2);
+               WriteString(MSG_ENTITY, this.target3);
+               WriteString(MSG_ENTITY, this.target4);
+               WriteString(MSG_ENTITY, this.targetname);
+               WriteString(MSG_ENTITY, this.killtarget);
+       }
+
+       if(f & 4)
+       {
+               WriteCoord(MSG_ENTITY, this.origin.x);
+               WriteCoord(MSG_ENTITY, this.origin.y);
+               WriteCoord(MSG_ENTITY, this.origin.z);
+       }
+
+       WriteShort(MSG_ENTITY, this.modelindex);
+       WriteCoord(MSG_ENTITY, this.mins.x);
+       WriteCoord(MSG_ENTITY, this.mins.y);
+       WriteCoord(MSG_ENTITY, this.mins.z);
+       WriteCoord(MSG_ENTITY, this.maxs.x);
+       WriteCoord(MSG_ENTITY, this.maxs.y);
+       WriteCoord(MSG_ENTITY, this.maxs.z);
+       WriteByte(MSG_ENTITY, bound(1, this.scale * 16, 255));
+
+       WriteCoord(MSG_ENTITY, this.movedir_x);
+       WriteCoord(MSG_ENTITY, this.movedir_y);
+       WriteCoord(MSG_ENTITY, this.movedir_z);
+
+       WriteCoord(MSG_ENTITY, this.angles_x);
+       WriteCoord(MSG_ENTITY, this.angles_y);
+       WriteCoord(MSG_ENTITY, this.angles_z);
 }
 
 #elif defined(CSQC)
 
 void trigger_common_read(bool withtarget)
 {SELFPARAM();
-       self.warpzone_isboxy = ReadByte();
-       self.scale = ReadByte();
+       int f = ReadByte();
+       self.warpzone_isboxy = (f & 1);
 
        if(withtarget)
        {
+               if(self.target) { strunzone(self.target); }
                self.target = strzone(ReadString());
+               if(self.target2) { strunzone(self.target2); }
                self.target2 = strzone(ReadString());
+               if(self.target3) { strunzone(self.target3); }
                self.target3 = strzone(ReadString());
+               if(self.target4) { strunzone(self.target4); }
                self.target4 = strzone(ReadString());
+               if(self.targetname) { strunzone(self.targetname); }
                self.targetname = strzone(ReadString());
+               if(self.killtarget) { strunzone(self.killtarget); }
                self.killtarget = strzone(ReadString());
        }
 
-       self.origin_x = ReadCoord();
-       self.origin_y = ReadCoord();
-       self.origin_z = ReadCoord();
+       if(f & 4)
+       {
+               self.origin_x = ReadCoord();
+               self.origin_y = ReadCoord();
+               self.origin_z = ReadCoord();
+       }
+       else
+               self.origin = '0 0 0';
        setorigin(self, self.origin);
 
+       self.modelindex = ReadShort();
        self.mins_x = ReadCoord();
        self.mins_y = ReadCoord();
        self.mins_z = ReadCoord();
        self.maxs_x = ReadCoord();
        self.maxs_y = ReadCoord();
        self.maxs_z = ReadCoord();
+       self.scale = ReadByte() / 16;
        setsize(self, self.mins, self.maxs);
 
        self.movedir_x = ReadCoord();
index c8e593f9cb53666eb6418b2d18033b7dac31783b..31b8be4416b83f7beb86644549b66197bca4628a 100644 (file)
@@ -22,7 +22,7 @@ const float   SPAWNFLAG_NOTOUCH = 1;
 
 // used elsewhere (will fix)
 #ifdef SVQC
-void trigger_common_write(bool withtarget);
+void trigger_common_write(entity this, bool withtarget);
 
 string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin);
 
index e05f519f4fb24d6decf4f8964e4a03d1e5dc22b1..dbf1e9e33b7fde472184323cb1cf54bc339d5fe9 100644 (file)
@@ -65,7 +65,7 @@ void turret_draw2d(entity this)
                return;
 
        float dist = vlen(self.origin - view_origin);
-       float t = (GetPlayerColor(player_localnum) + 1);
+       float t = (entcs_GetTeam(player_localnum) + 1);
 
        vector o;
        string txt;
index c7b84582239e1c129ab4de4d95d2e79fb6a82f66..44178f92f8178486eee45abbe90c2fff72345544 100644 (file)
@@ -3,26 +3,6 @@
 
 #include "all.qh"
 
-#ifndef MENUQC
-STATIC_INIT(vehicles_common_initialize)
-{
-#ifdef SVQC
-       addstat(STAT_HUD, AS_INT, hud);
-       addstat(STAT_VEHICLESTAT_HEALTH,  AS_INT, vehicle_health);
-       addstat(STAT_VEHICLESTAT_SHIELD,  AS_INT, vehicle_shield);
-       addstat(STAT_VEHICLESTAT_ENERGY,  AS_INT, vehicle_energy);
-
-       addstat(STAT_VEHICLESTAT_W2MODE, AS_INT, vehicle_weapon2mode);
-
-       addstat(STAT_VEHICLESTAT_AMMO1,   AS_INT, vehicle_ammo1);
-       addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1);
-
-       addstat(STAT_VEHICLESTAT_AMMO2,   AS_INT, vehicle_ammo2);
-       addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2);
-#endif // SVQC
-}
-#endif
-
 REGISTER_NET_LINKED(ENT_CLIENT_AUXILIARYXHAIR)
 
 #if defined(SVQC)
index be615772a9d5714eae39657e3c4b736c57a3ad5d..cc4fa0f122b9652f90a038e30fb3796ab7e16702 100644 (file)
@@ -132,13 +132,13 @@ void Vehicles_drawHUD(
        float barAlpha = autocvar_hud_progressbar_alpha * hudAlpha;
        float blinkValue = 0.55 + sin(time * 7) * 0.45;
 
-       float health  = getstati(STAT_VEHICLESTAT_HEALTH)  * 0.01;
-       float shield  = getstati(STAT_VEHICLESTAT_SHIELD)  * 0.01;
-       float energy  = getstati(STAT_VEHICLESTAT_ENERGY)  * 0.01;
-       float ammo1   = getstati(STAT_VEHICLESTAT_AMMO1)   * 0.01;
-       float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1) * 0.01;
-       float ammo2   = getstati(STAT_VEHICLESTAT_AMMO2)   * 0.01;
-       float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2) * 0.01;
+       float health  = STAT(VEHICLESTAT_HEALTH)  * 0.01;
+       float shield  = STAT(VEHICLESTAT_SHIELD)  * 0.01;
+       float energy  = STAT(VEHICLESTAT_ENERGY)  * 0.01;
+       float ammo1   = STAT(VEHICLESTAT_AMMO1)   * 0.01;
+       float reload1 = STAT(VEHICLESTAT_RELOAD1) * 0.01;
+       float ammo2   = STAT(VEHICLESTAT_AMMO2)   * 0.01;
+       float reload2 = STAT(VEHICLESTAT_RELOAD2) * 0.01;
 
        // HACK to deal with the inconsistent use of the vehicle stats
        ammo1 = (ammo1) ? ammo1 : energy;
index fbaf88c6f916526f1694ac2f0c2ca493bfc15b34..5293030c19fe9ecda1aad3c8e733edabc29eda72 100644 (file)
@@ -7,6 +7,6 @@ vector vehicleHud_Pos;
 void RaptorCBShellfragDraw(entity this);
 void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang);
 
-#define weapon2mode getstati(STAT_VEHICLESTAT_W2MODE)
+#define weapon2mode STAT(VEHICLESTAT_W2MODE)
 
 #endif
index b3f252e3b12597ed22b4bbae58ce9711c297bf19..423c8ec047380a2a84f20212bd4324ded774ff70 100644 (file)
@@ -42,14 +42,14 @@ float autocvar_g_vehicles_weapon_damagerate = 1;
 .entity gunner1;
 .entity gunner2;
 
-.float vehicle_health;  /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value.
-.float vehicle_energy;  /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value.
-.float vehicle_shield;  /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value.
+.float vehicle_health = _STAT(VEHICLESTAT_HEALTH);  /// If self is player this is 0..100 indicating precentage of health left on vehicle. If self is vehile, this is the real health value.
+.float vehicle_energy = _STAT(VEHICLESTAT_ENERGY);  /// If self is player this is 0..100 indicating precentage of energy left on vehicle. If self is vehile, this is the real energy value.
+.float vehicle_shield = _STAT(VEHICLESTAT_SHIELD);  /// If self is player this is 0..100 indicating precentage of shield left on vehicle. If self is vehile, this is the real shield value.
 
-.float vehicle_ammo1;   /// If self is player this is 0..100 indicating percentage of primary ammo left UNLESS value is already stored in vehicle_energy. If self is vehile, this is the real ammo1 value.
-.float vehicle_reload1; /// If self is player this is 0..100 indicating percentage of primary reload status. If self is vehile, this is the real reload1 value.
-.float vehicle_ammo2;   /// If self is player this is 0..100 indicating percentage of secondary ammo left. If self is vehile, this is the real ammo2 value.
-.float vehicle_reload2; /// If self is player this is 0..100 indicating percentage of secondary reload status. If self is vehile, this is the real reload2 value.
+.float vehicle_ammo1 = _STAT(VEHICLESTAT_AMMO1);   /// If self is player this is 0..100 indicating percentage of primary ammo left UNLESS value is already stored in vehicle_energy. If self is vehile, this is the real ammo1 value.
+.float vehicle_reload1 = _STAT(VEHICLESTAT_RELOAD1); /// If self is player this is 0..100 indicating percentage of primary reload status. If self is vehile, this is the real reload1 value.
+.float vehicle_ammo2 = _STAT(VEHICLESTAT_AMMO2);   /// If self is player this is 0..100 indicating percentage of secondary ammo left. If self is vehile, this is the real ammo2 value.
+.float vehicle_reload2 = _STAT(VEHICLESTAT_RELOAD2); /// If self is player this is 0..100 indicating percentage of secondary reload status. If self is vehile, this is the real reload2 value.
 
 .float sound_nexttime;
 const float VOL_VEHICLEENGINE = 1;
@@ -61,7 +61,7 @@ const float SVC_UPDATEENTITY  = 128; // Net.Protocol 0x80
 const float VHSF_NORMAL = 0;
 const float VHSF_FACTORY = 2;
 
-.int hud;
+.int hud = _STAT(HUD);
 .float dmg_time;
 
 .int volly_counter;
@@ -80,7 +80,7 @@ const float   DAMAGE_TARGETDRONE = 10;
 // vehicle functions
 .void(int _spawnflag) vehicle_spawn;  /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
 .bool(int _imp) vehicles_impulse;
-.int vehicle_weapon2mode;
+.int vehicle_weapon2mode = _STAT(VEHICLESTAT_W2MODE);
 .void(int exit_flags) vehicle_exit;
 .bool() vehicle_enter;
 const int VHEF_NORMAL = 0;  /// User pressed exit key
index 866a69eb2e8c59720f82774449835e8a0e6e38bb..a3739322bc7980df470e0890a2eb9bfabde92bcf 100644 (file)
@@ -804,7 +804,7 @@ spawnfunc(vehicle_raptor)
                                        dropmark.gravity = 1;
                                }
 
-                               float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2) * 0.01;
+                               float reload2 = STAT(VEHICLESTAT_RELOAD2) * 0.01;
                                if(reload2 == 1)
                                {
                                        setorigin(dropmark, pmove_org);
index fcadd2d43432cc7d2cc996cbb896483d5e1b2aa0..fc3bd9167a27121b7376da6c33cb684be0dbac14 100644 (file)
@@ -45,7 +45,7 @@
     #include "../../server/g_hook.qh"
 #endif
 #ifndef MENUQC
-#include "calculations.qc"
+       #include "calculations.qc"
 #endif
 #define IMPLEMENTATION
 #include "all.inc"
 
 // WEAPON PLUGIN SYSTEM
 
-WepSet _WepSet_FromWeapon(int a) {
+WepSet _WepSet_FromWeapon(int a)
+{
        a -= WEP_FIRST;
        if (Weapons_MAX > 24)
-       if (a >= 24) {
-               a -= 24;
-               if (Weapons_MAX > 48)
-               if (a >= 24) {
+               if (a >= 24)
+               {
                        a -= 24;
-                       return '0 0 1' * power2of(a);
+                       if (Weapons_MAX > 48)
+                               if (a >= 24)
+                               {
+                                       a -= 24;
+                                       return '0 0 1' * power2of(a);
+                               }
+                       return '0 1 0' * power2of(a);
                }
-               return '0 1 0' * power2of(a);
-       }
        return '1 0 0' * power2of(a);
 }
 #ifdef SVQC
-void WepSet_AddStat()
-{
-       addstat(STAT_WEAPONS, AS_INT, weapons_x);
-       if (Weapons_MAX > 24)
-       addstat(STAT_WEAPONS2, AS_INT, weapons_y);
-       if (Weapons_MAX > 48)
-       addstat(STAT_WEAPONS3, AS_INT, weapons_z);
-}
-void WepSet_AddStat_InMap()
-{
-       addstat(STAT_WEAPONSINMAP, AS_INT, weaponsinmap_x);
-       if (Weapons_MAX > 24)
-       addstat(STAT_WEAPONSINMAP2, AS_INT, weaponsinmap_y);
-       if (Weapons_MAX > 48)
-       addstat(STAT_WEAPONSINMAP3, AS_INT, weaponsinmap_z);
-}
-void WriteWepSet(float dst, WepSet w)
-{
-       if (Weapons_MAX > 48)
-       WriteInt72_t(dst, w);
-       else if (Weapons_MAX > 24)
-       WriteInt48_t(dst, w);
-       else
-       WriteInt24_t(dst, w.x);
-}
+       void WriteWepSet(float dst, WepSet w)
+       {
+               if (Weapons_MAX > 48) WriteInt72_t(dst, w);
+               else if (Weapons_MAX > 24) WriteInt48_t(dst, w);
+               else WriteInt24_t(dst, w.x);
+       }
 #endif
 #ifdef CSQC
-WepSet WepSet_GetFromStat()
-{
-       WepSet w = '0 0 0';
-       w.x = getstati(STAT_WEAPONS);
-       if (Weapons_MAX > 24)
-       w.y = getstati(STAT_WEAPONS2);
-       if (Weapons_MAX > 48)
-       w.z = getstati(STAT_WEAPONS3);
-       return w;
-}
-WepSet WepSet_GetFromStat_InMap()
-{
-       WepSet w = '0 0 0';
-       w_x = getstati(STAT_WEAPONSINMAP);
-       if (Weapons_MAX > 24)
-       w_y = getstati(STAT_WEAPONSINMAP2);
-       if (Weapons_MAX > 48)
-       w_z = getstati(STAT_WEAPONSINMAP3);
-       return w;
-}
-WepSet ReadWepSet()
-{
-       if (Weapons_MAX > 48)
-       return ReadInt72_t();
-       if (Weapons_MAX > 24)
-       return ReadInt48_t();
-       return ReadInt24_t() * '1 0 0';
-}
+       WepSet WepSet_GetFromStat()
+       {
+               return STAT(WEAPONS);
+       }
+       WepSet WepSet_GetFromStat_InMap()
+       {
+               return STAT(WEAPONSINMAP);
+       }
+       WepSet ReadWepSet()
+       {
+               if (Weapons_MAX > 48) return ReadInt72_t();
+               if (Weapons_MAX > 24) return ReadInt48_t();
+               return ReadInt24_t() * '1 0 0';
+       }
 #endif
 
 string W_FixWeaponOrder(string order, float complete)
@@ -131,27 +101,26 @@ string W_FixWeaponOrder(string order, float complete)
 }
 string W_NameWeaponOrder_MapFunc(string s)
 {
-       entity wi;
-       if(s == "0" || stof(s))
+       int i = stof(s);
+       if (s == "0" || i)
        {
-               wi = get_weaponinfo(stof(s));
-               if(wi != WEP_Null)
-                       return wi.netname;
+               entity wi = Weapons_from(i);
+               if (wi != WEP_Null) return wi.netname;
        }
        return s;
 }
 
 string W_UndeprecateName(string s)
 {
-       switch ( s )
+       switch (s)
        {
-               case "nex"            : return "vortex";
-               case "rocketlauncher" : return "devastator";
-               case "laser"          : return "blaster";
-               case "minstanex"      : return "vaporizer";
+               case "nex": return "vortex";
+               case "rocketlauncher": return "devastator";
+               case "laser": return "blaster";
+               case "minstanex": return "vaporizer";
                case "grenadelauncher": return "mortar";
-               case "uzi"            : return "machinegun";
-               default               : return s;
+               case "uzi": return "machinegun";
+               default: return s;
        }
 }
 string W_NameWeaponOrder(string order)
@@ -160,13 +129,9 @@ string W_NameWeaponOrder(string order)
 }
 string W_NumberWeaponOrder_MapFunc(string s)
 {
-       int i;
-       if(s == "0" || stof(s))
-               return s;
+       if (s == "0" || stof(s)) return s;
        s = W_UndeprecateName(s);
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-               if(s == get_weaponinfo(i).netname)
-                       return ftos(i);
+       FOREACH(Weapons, it != WEP_Null && it.netname == s, LAMBDA(return ftos(i)));
        return s;
 }
 string W_NumberWeaponOrder(string order)
@@ -185,28 +150,29 @@ void W_FixWeaponOrder_BuildImpulseList_swap(int i, int j, entity pass)
 }
 float W_FixWeaponOrder_BuildImpulseList_cmp(int i, int j, entity pass)
 {
-       entity e1, e2;
-       float d;
-       e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
-       e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
-       d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
-       if(d != 0)
-               return -d; // high impulse first!
-       return
-               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
-               -
-               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
-               ; // low char index first!
+       int si = W_FixWeaponOrder_BuildImpulseList_buf[i];
+       Weapon e1 = Weapons_from(si);
+       int sj = W_FixWeaponOrder_BuildImpulseList_buf[j];
+       Weapon e2 = Weapons_from(sj);
+       int d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
+       if (d != 0) return -d;  // high impulse first!
+       return strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "),
+               sprintf(" %d ", si), 0)
+              -
+              strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "),
+               sprintf(" %d ", sj), 0)
+        // low char index first!
 }
 string W_FixWeaponOrder_BuildImpulseList(string o)
 {
        int i;
        W_FixWeaponOrder_BuildImpulseList_order = o;
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+       for (i = WEP_FIRST; i <= WEP_LAST; ++i)
                W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
-       heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
+       heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp,
+               world);
        o = "";
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+       for (i = WEP_FIRST; i <= WEP_LAST; ++i)
                o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
        W_FixWeaponOrder_BuildImpulseList_order = string_null;
        return substring(o, 1, -1);
@@ -219,8 +185,7 @@ string W_FixWeaponOrder_AllowIncomplete(string order)
 
 string W_FixWeaponOrder_ForceComplete(string order)
 {
-       if(order == "")
-               order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
+       if (order == "") order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
        return W_FixWeaponOrder(order, 1);
 }
 
@@ -231,14 +196,14 @@ void W_RandomWeapons(entity e, float n)
        WepSet result;
        remaining = e.weapons;
        result = '0 0 0';
-       for(i = 0; i < n; ++i)
+       for (i = 0; i < n; ++i)
        {
                RandomSelection_Init();
-               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-                       if(remaining & WepSet_FromWeapon(j))
-                               RandomSelection_Add(world, j, string_null, 1, 1);
-               result |= WepSet_FromWeapon(RandomSelection_chosen_float);
-               remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
+               for (j = WEP_FIRST; j <= WEP_LAST; ++j)
+                       if (remaining & WepSet_FromWeapon(Weapons_from(j))) RandomSelection_Add(NULL, j, string_null, 1, 1);
+               Weapon w = Weapons_from(RandomSelection_chosen_float);
+               result |= WepSet_FromWeapon(w);
+               remaining &= ~WepSet_FromWeapon(w);
        }
        e.weapons = result;
 }
@@ -253,60 +218,388 @@ string GetAmmoPicture(.int ammotype)
                case ammo_cells:   return ITEM_Cells.m_icon;
                case ammo_plasma:  return ITEM_Plasma.m_icon;
                case ammo_fuel:    return ITEM_JetpackFuel.m_icon;
-               default: return ""; // wtf, no ammo type?
+               default: return "";  // wtf, no ammo type?
        }
 }
 
 #ifdef CSQC
-.int GetAmmoFieldFromNum(int i)
-{
-       switch(i)
+       .int GetAmmoFieldFromNum(int i)
        {
-               case 0: return ammo_shells;
-               case 1: return ammo_nails;
-               case 2: return ammo_rockets;
-               case 3: return ammo_cells;
-               case 4: return ammo_plasma;
-               case 5: return ammo_fuel;
-               default: return ammo_none;
+               switch (i)
+               {
+                       case 0: return ammo_shells;
+                       case 1: return ammo_nails;
+                       case 2: return ammo_rockets;
+                       case 3: return ammo_cells;
+                       case 4: return ammo_plasma;
+                       case 5: return ammo_fuel;
+                       default: return ammo_none;
+               }
        }
-}
 
-int GetAmmoStat(.int ammotype)
-{
-       switch(ammotype)
+       int GetAmmoStat(.int ammotype)
        {
-               case ammo_shells: return STAT_SHELLS;
-               case ammo_nails: return STAT_NAILS;
-               case ammo_rockets: return STAT_ROCKETS;
-               case ammo_cells: return STAT_CELLS;
-               case ammo_plasma: return STAT_PLASMA;
-               case ammo_fuel: return STAT_FUEL;
-               default: return -1;
+               switch (ammotype)
+               {
+                       case ammo_shells: return STAT_SHELLS;
+                       case ammo_nails: return STAT_NAILS;
+                       case ammo_rockets: return STAT_ROCKETS;
+                       case ammo_cells: return STAT_CELLS;
+                       case ammo_plasma: return STAT_PLASMA.m_id;
+                       case ammo_fuel: return STAT_FUEL.m_id;
+                       default: return -1;
+               }
        }
-}
 #endif
 
 string W_Sound(string w_snd)
 {
        string output = strcat("weapons/", w_snd);
 #ifdef SVQC
-       MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
-       return weapon_sound_output;
+               MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
+               return weapon_sound_output;
 #else
-       return output;
+               return output;
 #endif
 }
 
 string W_Model(string w_mdl)
 {
        string output = strcat("models/weapons/", w_mdl);
-#ifdef SVQC
        MUTATOR_CALLHOOK(WeaponModel, w_mdl, output);
        return weapon_model_output;
+}
+
+#ifndef MENUQC
+vector shotorg_adjustfromclient(vector vecs, float y_is_right, float algn)
+{
+       switch (algn)
+       {
+               default:
+               case 3:
+                       // right alignment
+                       break;
+               case 4:
+                       // left
+                       vecs.y = -vecs.y;
+                       break;
+               case 1:
+               case 2:
+                       // center
+                       vecs.y = 0;
+                       vecs.z -= 2;
+                       break;
+       }
+       return vecs;
+}
+
+vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn)
+{
+#ifdef SVQC
+       string s;
+#endif
+       if (visual)
+       {
+               vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
+       }
+#ifdef SVQC
+       else if (autocvar_g_shootfromeye)
+       {
+               vecs.y = vecs.z = 0;
+       }
+       else if (autocvar_g_shootfromcenter)
+       {
+               vecs.y = 0;
+               vecs.z -= 2;
+       }
+       else if ((s = autocvar_g_shootfromfixedorigin) != "")
+       {
+               vector v = stov(s);
+               if (y_is_right) v.y = -v.y;
+               if (v.x != 0) vecs.x = v.x;
+               vecs.y = v.y;
+               vecs.z = v.z;
+       }
+#endif
+       else  // just do the same as top
+       {
+               vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
+       }
+
+       return vecs;
+}
+
+#define shotorg_adjust shotorg_adjust_values
+
+/**
+ * supported formats:
+ *
+ * 1. simple animated model, muzzle flash handling on h_ model:
+ *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
+ *      tags:
+ *        shot = muzzle end (shot origin, also used for muzzle flashes)
+ *        shell = casings ejection point (must be on the right hand side of the gun)
+ *        weapon = attachment for v_tuba.md3
+ *    v_tuba.md3 - first and third person model
+ *    g_tuba.md3 - pickup model
+ *
+ * 2. simple animated model, muzzle flash handling on v_ model:
+ *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
+ *      tags:
+ *        weapon = attachment for v_tuba.md3
+ *    v_tuba.md3 - first and third person model
+ *      tags:
+ *        shot = muzzle end (shot origin, also used for muzzle flashes)
+ *        shell = casings ejection point (must be on the right hand side of the gun)
+ *    g_tuba.md3 - pickup model
+ *
+ * 3. fully animated model, muzzle flash handling on h_ model:
+ *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
+ *      tags:
+ *        shot = muzzle end (shot origin, also used for muzzle flashes)
+ *        shell = casings ejection point (must be on the right hand side of the gun)
+ *        handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes)
+ *    v_tuba.md3 - third person model
+ *    g_tuba.md3 - pickup model
+ *
+ * 4. fully animated model, muzzle flash handling on v_ model:
+ *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
+ *      tags:
+ *        shot = muzzle end (shot origin)
+ *        shell = casings ejection point (must be on the right hand side of the gun)
+ *    v_tuba.md3 - third person model
+ *      tags:
+ *        shot = muzzle end (for muzzle flashes)
+ *    g_tuba.md3 - pickup model
+ *
+ * writes:
+ *   this.origin, this.angles
+ *   this.weaponchild
+ *   this.movedir, this.view_ofs
+ *   attachment stuff
+ *   anim stuff
+ * to free:
+ *   call again with ""
+ *   remove the ent
+ */
+void CL_WeaponEntity_SetModel(entity this, string name)
+{
+       if (name == "")
+       {
+               this.model = "";
+               if (this.weaponchild) remove(this.weaponchild);
+               this.weaponchild = NULL;
+               this.movedir = '0 0 0';
+               this.spawnorigin = '0 0 0';
+               this.oldorigin = '0 0 0';
+               this.anim_fire1  = '0 1 0.01';
+               this.anim_fire2  = '0 1 0.01';
+               this.anim_idle   = '0 1 0.01';
+               this.anim_reload = '0 1 0.01';
+       }
+       else
+       {
+               // if there is a child entity, hide it until we're sure we use it
+               if (this.weaponchild) this.weaponchild.model = "";
+               _setmodel(this, W_Model(strcat("v_", name, ".md3")));
+               int v_shot_idx;  // used later
+               (v_shot_idx = gettagindex(this, "shot")) || (v_shot_idx = gettagindex(this, "tag_shot"));
+
+               _setmodel(this, W_Model(strcat("h_", name, ".iqm")));
+               // preset some defaults that work great for renamed zym files (which don't need an animinfo)
+               this.anim_fire1  = animfixfps(this, '0 1 0.01', '0 0 0');
+               this.anim_fire2  = animfixfps(this, '1 1 0.01', '0 0 0');
+               this.anim_idle   = animfixfps(this, '2 1 0.01', '0 0 0');
+               this.anim_reload = animfixfps(this, '3 1 0.01', '0 0 0');
+
+               // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
+               // if we don't, this is a "real" animated model
+               string t;
+               if ((t = "weapon", gettagindex(this, t)) || (t = "tag_weapon", gettagindex(this, t)))
+               {
+                       if (!this.weaponchild)
+                       {
+                               this.weaponchild = new(weaponchild);
+                               make_pure(this.weaponchild);
+#ifdef CSQC
+                               this.weaponchild.drawmask = MASK_NORMAL;
+                               this.weaponchild.renderflags |= RF_VIEWMODEL;
+#endif
+                       }
+                       _setmodel(this.weaponchild, W_Model(strcat("v_", name, ".md3")));
+                       setattachment(this.weaponchild, this, t);
+               }
+               else
+               {
+                       if (this.weaponchild) remove(this.weaponchild);
+                       this.weaponchild = NULL;
+               }
+
+               setorigin(this, '0 0 0');
+               this.angles = '0 0 0';
+               this.frame = 0;
+#ifdef SVQC
+               this.viewmodelforclient = NULL;
+#else
+               this.renderflags &= ~RF_VIEWMODEL;
+#endif
+               if (v_shot_idx)  // v_ model attached to invisible h_ model
+               {
+                       this.movedir = gettaginfo(this.weaponchild, v_shot_idx);
+               }
+               else
+               {
+                       int idx;
+                       if ((idx = gettagindex(this, "shot")) || (idx = gettagindex(this, "tag_shot")))
+                       {
+                               this.movedir = gettaginfo(this, idx);
+                       }
+                       else
+                       {
+                               LOG_WARNINGF("weapon model %s does not support the 'shot' tag, will display shots TOTALLY wrong\n",
+                                       this.model);
+                               this.movedir = '0 0 0';
+                       }
+               }
+               {
+                       int idx = 0;
+                       // v_ model attached to invisible h_ model
+                       if (this.weaponchild
+                           && ((idx = gettagindex(this.weaponchild, "shell")) || (idx = gettagindex(this.weaponchild, "tag_shell"))))
+                       {
+                               this.spawnorigin = gettaginfo(this.weaponchild, idx);
+                       }
+                       else if ((idx = gettagindex(this, "shell")) || (idx = gettagindex(this, "tag_shell")))
+                       {
+                               this.spawnorigin = gettaginfo(this, idx);
+                       }
+                       else
+                       {
+                               LOG_WARNINGF("weapon model %s does not support the 'shell' tag, will display casings wrong\n",
+                                       this.model);
+                               this.spawnorigin = this.movedir;
+                       }
+               }
+               if (v_shot_idx)
+               {
+                       this.oldorigin = '0 0 0';  // use regular attachment
+               }
+               else
+               {
+                       int idx;
+                       if (this.weaponchild)
+                               (idx = gettagindex(this, "weapon")) || (idx = gettagindex(this, "tag_weapon"));
+                       else
+                               (idx = gettagindex(this, "handle")) || (idx = gettagindex(this, "tag_handle"));
+                       if (idx)
+                       {
+                               this.oldorigin = this.movedir - gettaginfo(this, idx);
+                       }
+                       else
+                       {
+                               LOG_WARNINGF(
+                                       "weapon model %s does not support the 'handle' tag "
+                                       "and neither does the v_ model support the 'shot' tag, "
+                                       "will display muzzle flashes TOTALLY wrong\n",
+                                       this.model);
+                               this.oldorigin = '0 0 0';  // there is no way to recover from this
+                       }
+               }
+
+#ifdef SVQC
+               this.viewmodelforclient = this.owner;
+#else
+               this.renderflags |= RF_VIEWMODEL;
+#endif
+       }
+
+       this.view_ofs = '0 0 0';
+
+       if (this.movedir.x >= 0)
+       {
+#ifdef SVQC
+               int algn = this.owner.cvar_cl_gunalign;
+#else
+               int algn = autocvar_cl_gunalign;
+#endif
+               vector v = this.movedir;
+               this.movedir = shotorg_adjust(v, false, false, algn);
+               this.view_ofs = shotorg_adjust(v, false, true, algn) - v;
+       }
+       int compressed_shotorg = compressShotOrigin(this.movedir);
+       // make them match perfectly
+#ifdef SVQC
+       this.movedir = decompressShotOrigin(this.owner.stat_shotorg = compressed_shotorg);
 #else
-       return output;
+       this.movedir = decompressShotOrigin(compressed_shotorg);
 #endif
+
+       this.spawnorigin += this.view_ofs;  // offset the casings origin by the same amount
+
+       // check if an instant weapon switch occurred
+       setorigin(this, this.view_ofs);
+       // reset animstate now
+       this.wframe = WFRAME_IDLE;
+       setanim(this, this.anim_idle, true, false, true);
 }
+#endif
+
+#ifndef MENUQC
+
+REGISTER_NET_TEMP(wframe)
+#ifdef CSQC
+NET_HANDLE(wframe, bool isNew)
+{
+       vector a;
+       a.x = ReadCoord();
+    a.y = ReadCoord();
+    a.z = ReadCoord();
+       bool restartanim = ReadByte();
+       anim_set(viewmodel, a, !restartanim, restartanim, restartanim);
+       viewmodel.state = ReadByte();
+       viewmodel.weapon_nextthink = ReadFloat();
+       viewmodel.alpha = ReadByte() / 255;
+       switch (viewmodel.state)
+       {
+               case WS_RAISE:
+               case WS_DROP:
+                       viewmodel.weapon_switchdelay = ReadFloat();
+                       break;
+        default:
+            viewmodel.weapon_switchdelay = 0;
+            break;
+       }
+       return true;
+}
+#endif
+
+#ifdef SVQC
+void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim)
+{
+       if (!IS_REAL_CLIENT(actor)) return;
+       int channel = MSG_ONE;
+       msg_entity = actor;
+       WriteHeader(channel, wframe);
+       WriteCoord(channel, a.x);
+       WriteCoord(channel, a.y);
+       WriteCoord(channel, a.z);
+       WriteByte(channel, restartanim);
+       WriteByte(channel, weaponentity.state);
+       WriteFloat(channel, weaponentity.weapon_nextthink);
+       WriteByte(channel, weaponentity.m_alpha * 255);
+       Weapon w = Weapons_from(actor.weapon);
+       switch (weaponentity.state)
+       {
+               case WS_RAISE:
+                       WriteFloat(channel, w.switchdelay_raise);
+                       break;
+               case WS_DROP:
+                       WriteFloat(channel, w.switchdelay_drop);
+                       break;
+       }
+}
+#endif
+
+#endif
 
 #endif
index 8d62426daf61ccf15ccded49523d5d50499c559c..7e4d390ba698ef4be96ed7ff6c53c954f94a83ed 100644 (file)
@@ -8,8 +8,6 @@
 // weapon sets
 typedef vector WepSet;
 #ifdef SVQC
-void WepSet_AddStat();
-void WepSet_AddStat_InMap();
 void WriteWepSet(float dest, WepSet w);
 #endif
 
@@ -34,13 +32,12 @@ WepSet ReadWepSet();
 
 REGISTRY(Weapons, 72) // Increase as needed. Can be up to 72.
 #define Weapons_from(i) _Weapons_from(i, WEP_Null)
-#define get_weaponinfo(i) Weapons_from(i)
 REGISTER_REGISTRY(Weapons)
 STATIC_INIT(WeaponPickup) { FOREACH(Weapons, true, LAMBDA(it.m_pickup = NEW(WeaponPickup, it))); }
 
 .WepSet m_wepset;
 #define WEPSET(id) (WEP_##id.m_wepset)
-#define WepSet_FromWeapon(i) (Weapons_from(i).m_wepset)
+#define WepSet_FromWeapon(it) ((it).m_wepset)
 WepSet _WepSet_FromWeapon(int i);
 STATIC_INIT(WepSets)
 {
@@ -171,7 +168,44 @@ STATIC_INIT(register_weapons_done)
     for (int i = Weapons_MAX - 1; i >= 1; --i)
         if (Weapons_from(i))
             weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
-    weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
+    weaponorder_byid = strzone(substring(weaponorder_byid, 1, -1));
 }
 
+#ifndef MENUQC
+
+.entity weaponchild;
+.entity exteriorweaponentity;
+.vector weaponentity_glowmod;
+
+//.int weapon; // current weapon
+#ifdef SVQC
+.int switchweapon = _STAT(SWITCHWEAPON);
+.int switchingweapon = _STAT(SWITCHINGWEAPON);
+#endif
+.string weaponname; // name of .weapon
+
+.vector spawnorigin; // for casings
+
+// weapon animation vectors:
+.vector anim_fire1;
+.vector anim_fire2;
+.vector anim_idle;
+.vector anim_reload;
+
+// static frame globals
+
+ENUMCLASS(WFRAME)
+CASE(WFRAME, DONTCHANGE)
+CASE(WFRAME, FIRE1)
+CASE(WFRAME, FIRE2)
+CASE(WFRAME, IDLE)
+CASE(WFRAME, RELOAD)
+ENUMCLASS_END(WFRAME)
+
+.WFRAME wframe;
+
+vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
+void CL_WeaponEntity_SetModel(entity this, string name);
+#endif
+
 #endif
index 3ee4a684a26bff97bd44c17482e62ca6b5137a8c..ad90baa6fe3eb399445421a0a239c8d25ad4e52a 100644 (file)
@@ -24,17 +24,15 @@ float W_Config_Queue_Compare(int root, int child, entity pass)
 
 void Dump_Weapon_Settings()
 {
-       int i, x, totalsettings = 0;
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-       {
+       int totalweapons = 0, totalsettings = 0;
+       FOREACH(Weapons, it != WEP_Null, LAMBDA(
                // step 1: clear the queue
                WEP_CONFIG_COUNT = 0;
-               for(x = 0; x <= MAX_WEP_CONFIG; ++x)
+               for (int x = 0; x <= MAX_WEP_CONFIG; ++x)
                        { wep_config_queue[x] = string_null; }
 
                // step 2: build new queue
-               Weapon w = get_weaponinfo(i);
-               w.wr_config(w);
+               it.wr_config(it);
 
                // step 3: sort queue
                heapsort(WEP_CONFIG_COUNT, W_Config_Queue_Swap, W_Config_Queue_Compare, world);
@@ -43,22 +41,23 @@ void Dump_Weapon_Settings()
                WEP_CONFIG_WRITETOFILE(sprintf(
                        "// {{{ #%d: %s%s\n",
                        i,
-                       WEP_NAME(i),
-                       (((get_weaponinfo(i)).spawnflags & WEP_FLAG_MUTATORBLOCKED) ? " (MUTATOR WEAPON)" : "")
+                       it.m_name,
+                       ((it.spawnflags & WEP_FLAG_MUTATORBLOCKED) ? " (MUTATOR WEAPON)" : "")
                ));
-               for(x = 0; x <= WEP_CONFIG_COUNT; ++x) { WEP_CONFIG_WRITETOFILE(wep_config_queue[x]); }
+               for (int x = 0; x <= WEP_CONFIG_COUNT; ++x) { WEP_CONFIG_WRITETOFILE(wep_config_queue[x]); }
                WEP_CONFIG_WRITETOFILE("// }}}\n");
 
                // step 5: debug info
-               LOG_INFO(sprintf("#%d: %s: %d settings...\n", i, WEP_NAME(i), WEP_CONFIG_COUNT));
+               LOG_INFO(sprintf("#%d: %s: %d settings...\n", i, it.m_name, WEP_CONFIG_COUNT));
+               totalweapons += 1;
                totalsettings += WEP_CONFIG_COUNT;
-       }
+       ));
 
        // clear queue now that we're finished
        WEP_CONFIG_COUNT = 0;
-       for(x = 0; x <= MAX_WEP_CONFIG; ++x)
+       for(int x = 0; x <= MAX_WEP_CONFIG; ++x)
                { wep_config_queue[x] = string_null; }
 
        // extra information
-       LOG_INFO(sprintf("Totals: %d weapons, %d settings\n", (i - 1), totalsettings));
+       LOG_INFO(sprintf("Totals: %d weapons, %d settings\n", totalweapons, totalsettings));
 }
index 3a878a461d1f933a93160409ae4f873e5aae5ff7..bc98da4330f81278254b76c9296d1a4b12f24552 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef WEAPON_H
 #define WEAPON_H
 #include "../items/item/pickup.qh"
+#include "../stats.qh"
 
 const int MAX_WEAPONSLOTS = 2;
 .entity weaponentities[MAX_WEAPONSLOTS];
@@ -17,6 +18,27 @@ int weaponslot(.entity weaponentity)
        return 0;
 }
 
+// weapon states (actor.(weaponentity).state)
+/** no weapon selected */
+const int WS_CLEAR  = 0;
+/** raise frame */
+const int WS_RAISE  = 1;
+/** deselecting frame */
+const int WS_DROP   = 2;
+/** fire state */
+const int WS_INUSE  = 3;
+/** idle frame */
+const int WS_READY  = 4;
+
+#ifdef SVQC
+.int ammo_shells;
+.int ammo_nails;
+.int ammo_rockets;
+.int ammo_cells;
+.int ammo_plasma = _STAT(PLASMA);
+.int ammo_fuel = _STAT(FUEL);
+.int ammo_none;
+#else
 .int ammo_shells;
 .int ammo_nails;
 .int ammo_rockets;
@@ -24,6 +46,7 @@ int weaponslot(.entity weaponentity)
 .int ammo_plasma;
 .int ammo_fuel;
 .int ammo_none;
+#endif
 
 /** fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A" */
 CLASS(Weapon, Object)
@@ -95,6 +118,8 @@ CLASS(Weapon, Object)
         // no weapon specific image for this weapon
         return false;
     }
+    /** (CLIENT) weapon specific glow */
+    METHOD(Weapon, wr_glow, vector(Weapon this)) { return '0 0 0'; }
     /** (SERVER) the weapon is dropped */
     METHOD(Weapon, wr_drop, void(Weapon this)) {}
     /** (SERVER) a weapon is picked up */
@@ -193,6 +218,6 @@ string W_Model(string w_mdl);
 
 // other useful macros
 #define WEP_AMMO(wpn) (WEP_##wpn.ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
-#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).m_name)
+#define WEP_NAME(wpn) ((Weapons_from(wpn)).m_name)
 
 #endif
index 83d7e3fcbf23ec1ca254557df940f6a94a5fade7..7c9d64c01abed4d09077f4a29d2e0546dee57ac2 100644 (file)
@@ -670,7 +670,7 @@ void Arc_Smoke()
                                                weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
                                        else
                                        #endif
-                                               weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+                                               weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), w_ready);
                                }
 
                                if((!actor.arc_beam) || wasfreed(actor.arc_beam))
index 209bd2dd0e62f43754cd88272dc27f151df13a72..300622289b8af9656fcab2214a3c61239140c946 100644 (file)
@@ -575,8 +575,7 @@ void W_Crylink_Attack2(Weapon thiswep)
                METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
                {
                        if(autocvar_g_balance_crylink_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        }
 
                        if(fire & 1)
index d6ffd50d68b5acd281a97aa91cd24f7419eb09dd..6a841c9eb4186eac9cd17a2b64afb7a67a0d0a87 100644 (file)
@@ -526,8 +526,7 @@ void W_Devastator_Attack(Weapon thiswep)
                METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
                {
                        if(WEP_CVAR(devastator, reload_ammo) && actor.clip_load < WEP_CVAR(devastator, ammo)) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else {
                                if(fire & 1)
                                {
index 0f48bb2591688df274c36ccea961186d9d94140a..30dd6d74a3813394a268c59532577ed099d5fd65 100644 (file)
@@ -461,8 +461,7 @@ void W_Electro_CheckAttack(Weapon thiswep, entity actor, .entity weaponentity, i
 
                                if(!ammo_amount)
                                {
-                                       Weapon w = get_weaponinfo(actor.weapon);
-                                       w.wr_reload(w);
+                                       thiswep.wr_reload(thiswep);
                                        return;
                                }
                        }
index 859b54c959416077166498d37e5f097e3d59b773..a5066017a974855caeeb9b7994c79b40ca572e61 100644 (file)
@@ -386,8 +386,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, .entity weaponentity)
                self.hagar_warning = false;
 
                // we aren't checking ammo during an attack, so we must do it here
-               Weapon w = get_weaponinfo(self.weapon);
-               if(!(w.wr_checkammo1(w) + w.wr_checkammo2(w)))
+               if(!(thiswep.wr_checkammo1(thiswep) + thiswep.wr_checkammo2(thiswep)))
                if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
@@ -412,8 +411,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, .entity weaponentity)
                        if(loadable_secondary)
                                W_Hagar_Attack2_Load(thiswep, weaponentity); // must always run each frame
                        if(autocvar_g_balance_hagar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else if((fire & 1) && !actor.hagar_load && !actor.hagar_loadblock) // not while secondary is loaded or awaiting reset
                        {
                                if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(hagar, refire)))
index 252cc96e34988c5c1698f864d4eb2a0a197e98f8..f99c700735d358e79d089f11c1b0f2c8fc66cdc2 100644 (file)
@@ -169,8 +169,7 @@ void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int
 
        if(actor.BUTTON_ATCK)
        {
-               Weapon w = get_weaponinfo(actor.weapon);
-               if(!w.wr_checkammo1(w))
+               if(!thiswep.wr_checkammo1(thiswep))
                if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
@@ -213,8 +212,7 @@ void W_HLAC_Attack2_Frame(Weapon thiswep)
                METHOD(HLAC, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
                {
                        if(autocvar_g_balance_hlac_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else if(fire & 1)
                        {
                                if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(hlac, refire)))
index 553381818394bf4df9b27d9539a13c7b3830efc4..7e79bc929f4c4538d0d7e9c8f89c93ef8e4f01ef 100644 (file)
@@ -146,8 +146,7 @@ void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentit
        }
        if(actor.BUTTON_ATCK)
        {
-               Weapon w = get_weaponinfo(actor.weapon);
-               if(!w.wr_checkammo2(w))
+               if(!thiswep.wr_checkammo2(thiswep))
                if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
@@ -173,8 +172,7 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
                return;
        }
 
-       Weapon w = get_weaponinfo(actor.weapon);
-       if(!w.wr_checkammo1(w))
+       if(!thiswep.wr_checkammo1(thiswep))
        if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
@@ -252,8 +250,7 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit
                METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
                {
                        if(WEP_CVAR(machinegun, reload_ammo) && actor.clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else
                        if(WEP_CVAR(machinegun, mode) == 1)
                        {
@@ -267,8 +264,7 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit
                                if(fire & 2)
                                if(weapon_prepareattack(thiswep, actor, weaponentity, true, 0))
                                {
-                                       Weapon w = get_weaponinfo(actor.weapon);
-                                       if(!w.wr_checkammo2(w))
+                                       if(!thiswep.wr_checkammo2(thiswep))
                                        if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                                        {
                                                W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
index 1365e61b992c62646e6d47489be593580a1e563c..2f1459f83d4735ba6e9a75934a7b0ebfb932e71f 100644 (file)
@@ -506,8 +506,7 @@ float W_MineLayer_PlacedMines(float detonate)
                        {
                                // not if we're holding the minelayer without enough ammo, but can detonate existing mines
                                if(!(W_MineLayer_PlacedMines(false) && actor.WEP_AMMO(MINE_LAYER) < WEP_CVAR(minelayer, ammo))) {
-                                       Weapon w = get_weaponinfo(actor.weapon);
-                                       w.wr_reload(w);
+                                       thiswep.wr_reload(thiswep);
                                }
                        }
                        else if(fire & 1)
index 36a3c0c9e66f9c5ee515ad17d057cf8bff2dc4d6..223d13ffb2dbb6a1452f672659c850d78e88e39d 100644 (file)
@@ -335,8 +335,7 @@ void W_Mortar_Attack2(Weapon thiswep)
                METHOD(Mortar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
                {
                        if(autocvar_g_balance_mortar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else if(fire & 1)
                        {
                                if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(mortar, refire)))
index e7cd2606c1c4a5abbeb8ab5589a53708dc274dbb..a639747db7f2c9493bec6be49ab50e7136d88bad 100644 (file)
@@ -87,7 +87,7 @@ void W_Rifle_Attack2()
 }
 
 .void() rifle_bullethail_attackfunc;
-.float rifle_bullethail_frame;
+.WFRAME rifle_bullethail_frame;
 .float rifle_bullethail_animtime;
 .float rifle_bullethail_refire;
 void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponentity, int fire)
@@ -113,7 +113,7 @@ void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponent
        }
 }
 
-void W_Rifle_BulletHail(.entity weaponentity, float mode, void() AttackFunc, float fr, float animtime, float refire)
+void W_Rifle_BulletHail(.entity weaponentity, float mode, void() AttackFunc, WFRAME fr, float animtime, float refire)
 {SELFPARAM();
        // if we get here, we have at least one bullet to fire
        AttackFunc();
@@ -161,8 +161,7 @@ void W_Rifle_BulletHail(.entity weaponentity, float mode, void() AttackFunc, flo
                METHOD(Rifle, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
                {
                        if(autocvar_g_balance_rifle_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else
                        {
                                actor.rifle_accumulator = bound(time - WEP_CVAR(rifle, bursttime), actor.rifle_accumulator, time);
@@ -179,8 +178,7 @@ void W_Rifle_BulletHail(.entity weaponentity, float mode, void() AttackFunc, flo
                                        if(WEP_CVAR(rifle, secondary))
                                        {
                                                if(WEP_CVAR_SEC(rifle, reload)) {
-                                                       Weapon w = get_weaponinfo(actor.weapon);
-                                                       w.wr_reload(w);
+                                                       thiswep.wr_reload(thiswep);
                                                } else
                                                {
                                                        if(weapon_prepareattack_check(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(rifle, refire)))
index 533b7c944acfaa58fbe7ec437a75ecdb65280bcb..01c7feb887848f1ce0c157e2f19fd33c048323d0 100644 (file)
@@ -607,8 +607,7 @@ void W_Seeker_Fire_Tag(Weapon thiswep)
                METHOD(Seeker, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
                {
                        if(autocvar_g_balance_seeker_reload_ammo && actor.clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else if(fire & 1)
                        {
                                if(WEP_CVAR(seeker, type) == 1)
index dd1b1b1b9ca0cc93bda906d93bad71aa6486ff95..43a207e9686d0eff9c6da2f577c0b196305dd6d7 100644 (file)
@@ -744,7 +744,7 @@ void Draw_Shockwave(entity this)
        if(a < ALPHA_MIN_VISIBLE) { remove(self); }
 
        // WEAPONTODO: save this only once when creating the entity
-       vector sw_color = getcsqcplayercolor(self.sv_entnum - 1); // GetTeamRGB(GetPlayerColor(self.sv_entnum));
+       vector sw_color = entcs_GetColor(self.sv_entnum - 1); // GetTeamRGB(entcs_GetTeam(self.sv_entnum));
 
        // WEAPONTODO: trace to find what we actually hit
        vector endpos = (self.sw_shotorg + (self.sw_shotdir * self.sw_distance));
index 3ac26958ad00d82e946a76218d4367a32a207b25..c50eff100e81f04bb69551bc54d1eae0c6bc3af6 100644 (file)
@@ -197,8 +197,7 @@ void W_Shotgun_Attack2(Weapon thiswep, entity actor, .entity weaponentity, int f
 // alternate secondary weapon frames
 void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       Weapon w = get_weaponinfo(actor.weapon);
-       if (!w.wr_checkammo2(w))
+       if (!thiswep.wr_checkammo2(thiswep))
        if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
@@ -212,8 +211,7 @@ void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity
 }
 void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       Weapon w = get_weaponinfo(actor.weapon);
-       if (!w.wr_checkammo2(w))
+       if (!thiswep.wr_checkammo2(thiswep))
        if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
@@ -240,8 +238,7 @@ void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity
                        {
                                // don't force reload an empty shotgun if its melee attack is active
                                if(WEP_CVAR(shotgun, secondary) < 2) {
-                                       Weapon w = get_weaponinfo(actor.weapon);
-                                       w.wr_reload(w);
+                                       thiswep.wr_reload(thiswep);
                                }
                        }
                        else
index 6e7e386e5de48ef6b89101280ea01b3e2c5e79e7..7ab692f24dcd8779ca711bdb88f23367aab168da 100644 (file)
@@ -71,7 +71,7 @@ void SendCSQCVaporizerBeamParticle(entity player, int hit) {
        WriteCoord(MSG_BROADCAST, v.y);
        WriteCoord(MSG_BROADCAST, v.z);
        WriteByte(MSG_BROADCAST, hit);
-       WriteShort(MSG_BROADCAST, num_for_edict(player));
+       WriteByte(MSG_BROADCAST, num_for_edict(player));
        WriteByte(MSG_BROADCAST, player.team);
 }
 #elif defined(CSQC)
@@ -103,7 +103,15 @@ void VaporizerBeam_Draw(entity this)
        string tex = "particles/lgbeam";
        if(this.cnt)
                tex = "particles/gauntletbeam";
-       vector rgb = getcsqcplayercolor(this.sv_entnum - 1);
+       vector rgb;
+       //entity e = CSQCModel_server2csqc(this.sv_entnum - 1);
+       //if (e == NULL)
+       //{
+               rgb = colormapPaletteColor(stof(getplayerkeyvalue(this.sv_entnum - 1, "colors")) & 0x0F, true);
+               //rgb = '1 1 1';
+       //}
+       //else
+       //      rgb = e.glowmod;
        rgb *= (1 + autocvar_cl_vaporizerbeam_colorboost);
 
        float fail = (self.nextthink - time);
@@ -133,7 +141,9 @@ NET_HANDLE(TE_CSQC_VAPORBEAMPARTICLE, bool isNew)
        this.vorg1_x = ReadCoord(); this.vorg1_y = ReadCoord(); this.vorg1_z = ReadCoord();
        this.vorg2_x = ReadCoord(); this.vorg2_y = ReadCoord(); this.vorg2_z = ReadCoord();
        this.cnt = ReadByte();
-       this.sv_entnum = ReadShort();
+       int myowner = ReadByte();
+       this.owner = playerslots[myowner - 1];
+       this.sv_entnum = myowner;
        this.team = ReadByte() - 1;
 
        if(autocvar_cl_vaporizerbeam_particle)
@@ -337,11 +347,9 @@ void W_RocketMinsta_Attack3 ()
                        float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
                        // if the laser uses load, we also consider its ammo for reloading
                        if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && actor.clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else if(WEP_CVAR(vaporizer, reload_ammo) && actor.clip_load < vaporizer_ammo) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        }
                        if((fire & 1) && (actor.ammo_cells || !autocvar_g_rm) && !forbidWeaponUse(actor))
                        {
index dfb6354dd2dcb7c225539c159acd5e1e35749736..ded0eede4617043675147fb80c52c1aca7ea1a3b 100644 (file)
@@ -61,6 +61,37 @@ VORTEX_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 
+REGISTER_STAT(WEP_CVAR_vortex_charge, bool, WEP_CVAR(vortex, charge))
+REGISTER_STAT(WEP_CVAR_vortex_charge_animlimit, float, WEP_CVAR(vortex, charge_animlimit))
+
+#if defined(CSQC)
+float autocvar_g_weapon_charge_colormod_red_full;
+float autocvar_g_weapon_charge_colormod_red_half;
+float autocvar_g_weapon_charge_colormod_green_full;
+float autocvar_g_weapon_charge_colormod_blue_full;
+float autocvar_g_weapon_charge_colormod_blue_half;
+float autocvar_g_weapon_charge_colormod_green_half;
+float autocvar_g_weapon_charge_colormod_hdrmultiplier;
+
+METHOD(Vortex, wr_glow, vector(Vortex this))
+{
+       if (!STAT(WEP_CVAR_vortex_charge)) return '0 0 0';
+       float charge = STAT(VORTEX_CHARGE);
+       float animlimit = STAT(WEP_CVAR_vortex_charge_animlimit);
+       vector g;
+       g.x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, charge / animlimit);
+       g.y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, charge / animlimit);
+       g.z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, charge / animlimit);
+       if (charge > animlimit)
+       {
+               g.x += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (charge - animlimit) / (1 - animlimit);
+               g.y += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (charge - animlimit) / (1 - animlimit);
+               g.z += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (charge - animlimit) / (1 - animlimit);
+       }
+       return g;
+}
+#endif
+
 REGISTER_NET_TEMP(TE_CSQC_VORTEXBEAMPARTICLE)
 
 #if defined(SVQC)
@@ -92,7 +123,7 @@ NET_HANDLE(TE_CSQC_VORTEXBEAMPARTICLE, bool isNew)
        particles_alphamin = particles_alphamax = particles_fade = charge;
 
        if(!MUTATOR_CALLHOOK(Particles_VortexBeam, shotorg, endpos))
-       if(autocvar_cl_particles_oldvortexbeam && (getstati(STAT_ALLOW_OLDVORTEXBEAM) || isdemo()))
+       if(autocvar_cl_particles_oldvortexbeam && (STAT(ALLOW_OLDVORTEXBEAM) || isdemo()))
                WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM_OLD), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
        else
                WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum(EFFECT_VORTEX_BEAM), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
@@ -199,8 +230,7 @@ void W_Vortex_Attack(Weapon thiswep, float issecondary)
                                }
 
                        if(autocvar_g_balance_vortex_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) { // forced reload
-                               Weapon w = get_weaponinfo(actor.weapon);
-                               w.wr_reload(w);
+                               thiswep.wr_reload(thiswep);
                        } else
                        {
                                if(fire & 1)
index b9bcec58e60c6df31679667ea4a7ded1397333b5..ce39bca1bda2ff74ead4a9bb5d9a1399a120c132 100644 (file)
 #define pointparticles __pointparticles
 #define setmodel _setmodel
 
+#define STAT_FRAGLIMIT _STAT_FRAGLIMIT
+#define STAT_TIMELIMIT _STAT_TIMELIMIT
+#define STAT_MOVEVARS_TICRATE _STAT_MOVEVARS_TICRATE
+#define STAT_MOVEVARS_TIMESCALE _STAT_MOVEVARS_TIMESCALE
+#define STAT_MOVEVARS_GRAVITY _STAT_MOVEVARS_GRAVITY
+
 #include "upstream/csprogsdefs.qc"
 
 #undef true
 #undef pointparticles
 #undef setmodel
 
+#undef STAT_FRAGLIMIT
+#undef STAT_TIMELIMIT
+#undef STAT_MOVEVARS_TICRATE
+#undef STAT_MOVEVARS_TIMESCALE
+#undef STAT_MOVEVARS_GRAVITY
+
 #pragma noref 0
 
 #endif
diff --git a/qcsrc/dpdefs/doc.md b/qcsrc/dpdefs/doc.md
new file mode 100644 (file)
index 0000000..4ee5532
--- /dev/null
@@ -0,0 +1,224 @@
+# CSQC
+
+```
+
+// input:
+//   self
+.void() predraw;
+
+// input:
+//   time
+//   self
+.void() think;
+
+// 0 = keydown, key, character (EXT_CSQC)
+// 1 = keyup, key, character (EXT_CSQC)
+// 2 = mousemove relative, x, y (EXT_CSQC)
+// 3 = mousemove absolute, x, y (DP_CSQC)
+bool CSQC_InputEvent(int eventtype, int x, int y);
+
+void CSQC_UpdateView(int width, int height);
+bool CSQC_ConsoleCommand(string cmd);
+bool CSQC_Parse_TempEntity();
+bool CSQC_Parse_StuffCmd(string msg);
+bool CSQC_Parse_Print(string msg);
+bool CSQC_Parse_CenterPrint(string msg);
+bool CSQC_Event_Sound(int ent, int channel, string sample, float volume, float attenuation, vector pos, float speed, int flags);
+
+entity CSQC_Ent_Spawn(int entnum);
+void CSQC_Ent_Update(bool isnew);
+void CSQC_Ent_Remove();
+
+void CSQC_Init();
+void CSQC_Shutdown();
+
+// input:
+//   time
+//   self
+//   v_forward: forward
+//   v_right: right
+//   v_up: up
+// output:
+//   origin
+//   v_forward: forward
+//   v_right: right
+//   v_up: up
+//   trace_endpos: visorigin 
+.vector camera_transform(vector pos, vector ang);
+
+```
+
+# SVQC
+
+```
+
+.entity clientcamera;
+
+// input:
+//   time
+//   self
+void ClientDisconnect();
+
+// input:
+//   time
+void SV_Shutdown();
+
+// input:
+//   time
+void SV_PausedTic(float elapsed);
+
+// input:
+//   time
+//   self
+void SV_ChangeTeam(int color);
+
+// input:
+//   time
+//   self
+void ClientKill();
+
+// input:
+//   time
+//   self
+void RestoreGame();
+
+// input:
+//   time
+//   self
+//   parm1..n
+void ClientConnect();
+
+// input:
+//   time
+//   self
+//   parm1..n
+void PutClientInServer();
+
+// return false to remove
+.bool SendEntity(entity to, int sf);
+
+// input:
+//   time
+//   self
+void SV_OnEntityPreSpawnFunction();
+
+// input:
+//   time
+//   self
+void SV_OnEntityNoSpawnFunction();
+
+// input:
+//   time
+//   self
+void SV_OnEntityPostSpawnFunction();
+
+// input:
+//   time
+// output:
+//   parm1..n
+void SetNewParms();
+
+// input:
+//   
+.bool customizeentityforclient();
+
+// input:
+//   time
+//   self
+// output:
+//   parm1..n
+void SetChangeParms();
+
+// input:
+//   time
+//   self
+//   other
+//   trace_allsolid
+//   trace_startsolid
+//   trace_fraction
+//   trace_inwater
+//   trace_inopen
+//   trace_endpos: self.origin
+//   trace_plane_normal
+//   trace_plane_dist
+//   trace_ent: other
+//   trace_dpstartcontents
+//   trace_dphitcontents
+//   trace_dphitq3surfaceflags
+//   trace_dphittexturename
+.void touch();
+
+// when .watertype changes:
+.void contentstransition(int prev, int current);
+
+// input:
+//   time
+//   self
+//   other
+.void blocked();
+
+// input:
+//   time
+//   self
+.void movetypesteplandevent(vector vel);
+
+// input:
+//   time
+//   self
+void PlayerPreThink();
+
+// input:
+//   time
+//   self
+void PlayerPostThink();
+
+// input:
+//   time
+//   frametime
+void StartFrame();
+
+// input:
+//   time
+void EndFrame();
+
+// input:
+//   time
+//   self
+void SV_PlayerPhysics();
+
+// input:
+//   time
+//   self
+void SV_ParseClientCommand(string cmd);
+
+```
+
+# MENUQC
+
+```
+
+void m_keydown(int key, int ascii);
+
+void m_keyup(int key, int ascii);
+
+void m_draw(int width, int height);
+
+void m_toggle(int mode);
+
+int m_gethostcachecategory(int entry);
+
+void m_shutdown();
+
+void m_init();
+
+```
+
+# All
+
+```
+
+void URI_Get_Callback(int id, int status, string data);
+
+void GameCommand(string cmd);
+
+```
index 24d2df747cf1c3dd649189e8b4a77382532b9b7b..a63b43e22a58c879e8c378e91a037bd7b13b0bf4 100644 (file)
@@ -36,6 +36,7 @@
 #include "cvar.qh"
 #include "defer.qh"
 #include "draw.qh"
+#include "enumclass.qh"
 #include "file.qh"
 #include "functional.qh"
 #include "i18n.qh"
@@ -66,5 +67,6 @@
 #include "string.qh"
 #include "struct.qh"
 #include "test.qc"
+#include "unsafe.qh"
 #include "urllib.qc"
 #include "vector.qh"
index c2aae2b7b5476f529eaa977840852bdb5fa55045..b071805ef4136e0b06d2c4b4452f139c0e9e8968 100644 (file)
@@ -1,26 +1,36 @@
 #ifndef ARRAYLIST_H
 #define ARRAYLIST_H
 
-typedef int ArrayList;
+typedef entity ArrayList;
+.int al_buf;
+.int al_len;
 
-#define AL_declare(this) ArrayList this; int this##_len = (0)
-#define AL_init(this, n, default, T) \
+#define AL_NEW(this, n, default, T) \
        do \
        { \
-               this = buf_create(); \
-               this##_len = n; \
-               for (int i = 0; i < this##_len; ++i) \
+               ArrayList _al = this = new(ArrayList); \
+               make_pure(_al); \
+               _al.al_buf = buf_create(); \
+               for (int i = 0, _n = _al.al_len = n; i < _n; ++i) \
                { \
                        const _AL_type__##T() it = default; \
                        AL_set##T(this, i, it); \
                } \
        } \
        while (0)
-#define AL_delete(this) buf_del(this)
+
+#define AL_DELETE(this) \
+       do \
+       { \
+               buf_del(this.al_buf); \
+               remove(this); \
+               this = NULL; \
+       } \
+       while (0)
 
 #define _AL_type__s() string
-#define AL_gets(this, idx) bufstr_get(this, idx)
-#define AL_sets(this, idx, val) bufstr_set(this, idx, val)
+#define AL_gets(this, idx) bufstr_get(this.al_buf, idx)
+#define AL_sets(this, idx, val) bufstr_set(this.al_buf, idx, val)
 
 #define _AL_type__f() float
 #define AL_getf(this, idx) stof(AL_gets(this, idx))
@@ -34,7 +44,7 @@ typedef int ArrayList;
        do \
        { \
                const noref ArrayList _al = this; \
-               for (int i = 0, n = this##_len; i < n; ++i) \
+               for (int i = 0, n = _al.al_len; i < n; ++i) \
                { \
                        const noref _AL_type__##T() it = AL_get##T(_al, i); \
                        if (cond) { body } \
index e0eaccae11f957539f2d42f565b911482da16d89..ecc98b1a3c96c326bf4f9dcfcb13cb47bd7632fc 100644 (file)
@@ -129,35 +129,61 @@ void CSQCPlayer_SavePrediction(entity this)
 }
 
 void CSQC_ClientMovement_PlayerMove_Frame(entity this);
-void _Movetype_Physics_Frame(entity this, float movedt);
+void _Movetype_Physics_ClientFrame(entity this, float movedt);
 
 void Movetype_Physics_Spam(entity this)  // optimized
 {
-       _Movetype_Physics_Frame(this, PHYS_INPUT_TIMELENGTH);
+       _Movetype_Physics_ClientFrame(this, PHYS_INPUT_TIMELENGTH);
        if(wasfreed(this))
                return;
 
        this.avelocity = this.move_avelocity;
        this.velocity = this.move_velocity;
        this.angles = this.move_angles;
+       this.flags = BITSET(this.flags, FL_ONGROUND, boolean(this.move_flags & FL_ONGROUND));
+       this.flags = BITSET(this.flags, FL_WATERJUMP, boolean(this.move_flags & FL_WATERJUMP));
+       this.waterlevel = this.move_waterlevel;
+       this.watertype = this.move_watertype;
        setorigin(this, this.move_origin);
 }
 
+void CSQCPlayer_CheckWater(entity this)
+{
+       this.move_origin = this.origin;
+       this.move_waterlevel = this.waterlevel;
+       this.move_watertype = this.watertype;
+       _Movetype_CheckWater(this);
+       this.waterlevel = this.move_waterlevel;
+       this.watertype = this.move_watertype;
+}
+
 void CSQCPlayer_Physics(entity this)
 {
        if(autocvar_cl_movement)
        {
+               if(autocvar_cl_movement == 3)
+                       CSQCPlayer_CheckWater(this); // we apparently need to check water *before* physics so it can use this for water jump
+
                CSQC_ClientMovement_PlayerMove_Frame(this);
 
                if(autocvar_cl_movement == 3)
                {
                        this.move_origin = this.origin;
                        this.move_angles = this.angles;
-                       this.move_movetype = MOVETYPE_WALK; // temp
+                       //this.move_movetype = MOVETYPE_WALK; // temp
                        this.move_velocity = this.velocity;
                        this.move_avelocity = this.avelocity;
+                       this.move_flags = BITSET(this.move_flags, FL_ONGROUND, boolean(this.flags & FL_ONGROUND));
+                       this.move_flags = BITSET(this.move_flags, FL_WATERJUMP, boolean(this.flags & FL_WATERJUMP));
+                       this.move_waterlevel = this.waterlevel;
+                       this.move_watertype = this.watertype;
                        Movetype_Physics_Spam(this);
                }
+
+               this.pmove_flags =
+                               ((this.flags & FL_DUCKED) ? PMF_DUCKED : 0) |
+                               (!(this.flags & FL_JUMPRELEASED) ? PMF_JUMP_HELD : 0) |
+                               ((this.flags & FL_ONGROUND) ? PMF_ONGROUND : 0);
        }
 }
 
diff --git a/qcsrc/lib/enumclass.qh b/qcsrc/lib/enumclass.qh
new file mode 100644 (file)
index 0000000..2959565
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef ENUMCLASS_H
+#define ENUMCLASS_H
+
+#include "oo.qh"
+
+// purpose: prevent transposed parameter passing
+
+#if NDEBUG
+
+// zero overhead mode, use this for releases
+
+#define ENUMCLASS(id) typedef int id; enum {
+#define CASE(class, id) class##_##id,
+#define ENUMCLASS_END(id) };
+
+#else
+
+// edict overhead mode, use this for type checking
+
+#define ENUMCLASS(id) CLASS(id, Object)
+#define CASE(class, id) class class##_##id; STATIC_INIT(class##_##id) { class##_##id = NEW(class); }
+#define ENUMCLASS_END(id) ENDCLASS(id)
+
+#endif
+
+#endif
index 3773e16d1d2fdde2c904f6ac37812aab2d5a08a2..afb38ff95686509917343c9af5af6b43efb8faca 100644 (file)
@@ -2,6 +2,7 @@
 #define I18N_H
 
 #include "log.qh"
+#include "unsafe.qh"
 
 // translation helpers
 string prvm_language;
@@ -20,11 +21,36 @@ string language_filename(string s)
        return s;
 }
 
+#ifndef CTX_CACHE
+       #define CTX_CACHE 1
+#endif
+
+#if CTX_CACHE
+       ArrayList CTX_cache;
+       STATIC_INIT(CTX_cache)
+       {
+               AL_NEW(CTX_cache, 0, string_null, s);
+       }
+       SHUTDOWN(CTX_cache)
+       {
+               AL_DELETE(CTX_cache);
+       }
+#endif
+
 string CTX(string s)
 {
+#if CTX_CACHE
+               int i = strid(s);
+               string c = AL_gets(CTX_cache, i);
+               if (c) return c;
+#endif
        int p = strstrofs(s, "^", 0);
-       if (p < 0) return s;
-       return substring(s, p + 1, -1);
+       string ret = (p < 0) ? s : substring(s, p + 1, -1);
+#if CTX_CACHE
+        LOG_DEBUGF("CTX(\"%s\")\n", s);
+               AL_sets(CTX_cache, i, ret);
+#endif
+       return ret;
 }
 
 #define ZCTX(s) strzone(CTX(s))
index 57be59fcb895f076a772f426eba73cd94a1baf3f..3c2b650051eeee205ffa0b164e2234a0f2e890ad 100644 (file)
        while (0)
 
 #if defined(CSQC)
+       entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #402;
        entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #403;
+       entity(.float fld, float match, .entity tofield) _findchainflags_tofield = #450;
 #elif defined(SVQC)
+       entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #402;
        entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #403;
+       entity(.float fld, float match, .entity tofield) _findchainflags_tofield = #450;
 #elif defined(MENUQC)
+       entity(.string fld, string match, .entity tofield) _findchainstring_tofield = #26;
        entity(.entity fld, entity match, .entity tofield) findchainentity_tofield = #27;
+       entity(.float fld, float match, .entity tofield) _findchainflags_tofield = #88;
 #endif
 
 .entity _FOREACH_ENTITY_fld;
        } \
        while (0)
 
+#define FOREACH_ENTITY_FLAGS(fld, flags, body) \
+       do { \
+               int i = 0; \
+               for (entity it = _findchainflags_tofield(fld, flags, _FOREACH_ENTITY_next); it; (it = it._FOREACH_ENTITY_next, ++i)) \
+               { \
+                       body \
+               } \
+       } \
+       while (0)
+
+#define FOREACH_ENTITY_CLASS(class, cond, body) \
+       do { \
+               int i = 0; \
+               for (entity it = _findchainstring_tofield(classname, class, _FOREACH_ENTITY_next); it; (it = it._FOREACH_ENTITY_next, ++i)) \
+               { \
+                       if (cond) { body } \
+               } \
+       } \
+       while (0)
+
 #define FOREACH_ENTITY(cond, body) FOREACH_ENTITY_UNORDERED(cond, body)
 
 #define FOREACH(list, cond, body) FOREACH_LIST(list, enemy, cond, body)
index 4946daddee31ab90b326390d07ea43964ddc3e5c..3f57fdbc7214872dfad24b4de2fb0d10480185a0 100644 (file)
@@ -21,6 +21,7 @@ ENDCLASS(LinkedList)
  */
 entity LL_PUSH(LinkedList this, entity e)
 {
+       assert(this);
        LinkedListNode n = NEW(LinkedListNode);
        n.ll_data = e;
        LinkedListNode tail = n.ll_prev = this.ll_tail;
@@ -33,15 +34,45 @@ entity LL_PUSH(LinkedList this, entity e)
  */
 entity LL_POP(LinkedList this)
 {
+       assert(this);
        if (!this.ll_tail) return NULL;
        LinkedListNode n = this.ll_tail;
        entity e = n.ll_data;
        LinkedListNode prev = n.ll_prev;
-       if (prev) prev.ll_next = NULL;
+       if (prev) (this.ll_tail = prev).ll_next = NULL;
        else this.ll_head = this.ll_tail = NULL;
+       remove(n);
        return e;
 }
 
+#define LL_CLEAR(...) EVAL(OVERLOAD(LL_CLEAR, __VA_ARGS__))
+#define LL_CLEAR_1(this) LL_CLEAR_2(this, LAMBDA())
+#define LL_CLEAR_2(this, dtor) \
+       do \
+       { \
+               LinkedList _ll = this; \
+               assert(_ll); \
+               while (_ll.ll_tail) \
+               { \
+                       entity it = LL_POP(_ll); \
+                       if (!it) continue; \
+                       dtor \
+                       remove(it); \
+               } \
+       } \
+       while (0)
+
+#define LL_DELETE(...) EVAL(OVERLOAD(LL_DELETE, __VA_ARGS__))
+#define LL_DELETE_1(this) LL_DELETE_2(this, LAMBDA())
+#define LL_DELETE_2(this, dtor) \
+       do \
+       { \
+               LL_CLEAR(this, dtor); \
+               remove(this); \
+               this = NULL; \
+       } \
+       while (0)
+
 #define LL_EACH(list, cond, body) \
        do                                                                  \
        {                                                                   \
index e24bd8f05def2f24d60af912fa645ad290ce82d3..af2bab0f486a94b95a6795110f87a08c5d24fa1e 100644 (file)
        } \
        while (0)
 
-#define assert(expr, ...) \
+#define assert(expr, ...) _assert(LOG_SEVERE, expr, __VA_ARGS__)
+#define ASSERT(expr, ...) _assert(LOG_FATAL, expr, __VA_ARGS__)
+#define _assert(f, expr, then) \
        do \
        { \
-               if (!(expr)) LOG_WARNINGF(__VA_ARGS__); \
+               if (!(expr)) \
+               { \
+                       f("assertion failed: `" #expr "`\n"); \
+                       then; \
+               } \
        } \
        while (0)
 
+#define ASSERT_LESS(name, var, const) noref int name[(const - var + 1)];
+
 #define _LOG(f, level, s) f("[::"level "] ["__FILE__ ":%s:%.0f] %s", __FUNC__, __LINE__, s)
 
 #define  LOG_FATAL(...) _LOG_FATAL(strcat("", __VA_ARGS__))
@@ -84,11 +92,4 @@ noref bool autocvar_prvm_backtraceforwarnings;
        } \
        while (0)
 
-#define ASSERT(expr) \
-       do \
-       { \
-               if (!(expr)) LOG_FATAL("assertion failed: " #expr "\n"); \
-       } \
-       while (0)
-
 #endif
index 50461945722cbbf250b3b1f667be1e97f4ee1556..1e3d511c6ef00d00c2e18711bc59efeff38b9088 100644 (file)
                }
        }
 
+       void Net_UnlinkEntity(entity e)
+       {
+               e.SendEntity = func_null;
+       }
+
        .void() uncustomizeentityforclient;
        .float uncustomizeentityforclient_set;
 
@@ -187,7 +192,7 @@ STATIC_INIT(RegisterTempEntities_renumber)
                }
 
                #define ReadFloat() ReadCoord()
-        vector ReadVector() { vector v; v.x = ReadFloat(); v_y = ReadFloat(); v.z = ReadFloat(); return v; }
+        vector ReadVector() { vector v; v.x = ReadFloat(); v.y = ReadFloat(); v.z = ReadFloat(); return v; }
                vector ReadVector2D() { vector v; v.x = ReadFloat(); v.y = ReadFloat(); v.z = 0; return v; }
 
                float ReadApproxPastTime()
index e7d9a13b101b068f370d7eaf71c93550b7a6da83..d7e9df848865a02039757ba6f92e12d39ecc9b7f 100644 (file)
                (e).pure_data = true; \
        } \
        while (0)
+#define make_impure(e) \
+       do \
+       { \
+               (e).pure_data = false; \
+       } \
+       while (0)
 #define is_pure(e) ((e).pure_data)
 
 .string classname;
@@ -54,13 +60,16 @@ entity _clearentity_ent;
 STATIC_INIT(clearentity)
 {
        _clearentity_ent = new(clearentity);
+       make_pure(_clearentity_ent);
 }
 void clearentity(entity e)
 {
 #ifdef CSQC
                int n = e.entnum;
 #endif
+       bool was_pure = is_pure(e);
        copyentity(_clearentity_ent, e);
+       if (!was_pure) make_impure(e);
 #ifdef CSQC
                e.entnum = n;
 #endif
index 3b5e3305c600b55a343fb36e888267aff21f2b52..a2284b19448a10428963439464da0b91940a5b73 100644 (file)
@@ -4,10 +4,10 @@
 #include "oo.qh"
 
 #if 1
-       #define _R_MAP(r, max) AL_declare(r); STATIC_INIT(r) { AL_init(r, max, NULL, e); }
+       #define _R_MAP(r, max) ArrayList r; STATIC_INIT(r) { AL_NEW(r, max, NULL, e); }
        #define _R_GET(r, i) AL_gete(r, i)
        #define _R_SET(r, i, e) AL_sete(r, i, e)
-       #define _R_DEL(r) AL_delete(r)
+       #define _R_DEL(r) AL_DELETE(r)
 #else
        #define _R_MAP(r, max) entity r[max]
        #define _R_GET(r, i) r[i]
@@ -64,18 +64,29 @@ REGISTRY(Registries, BITS(8))
                if (registry##_COUNT >= registry##_MAX) LOG_FATALF("Registry capacity exceeded (%s)", ftos(registry##_MAX)); \
                entity this = id = inst; \
                this.registered_id = #id; \
-               this.fld = registry##_COUNT; \
-               _R_SET(_##registry, registry##_COUNT, this); \
-               ++registry##_COUNT; \
-               if (!registry##_first) registry##_first = this; \
-               if (registry##_last)   registry##_last.REGISTRY_NEXT = this; \
-               registry##_last = this; \
+               REGISTRY_PUSH(registry, fld, this); \
                Register_##id##_init(this); \
                Register_##id##_init_post(this); \
        } \
        ACCUMULATE_FUNCTION(Register##registry, Register_##id) \
        REGISTER_INIT(id)
 
+#define REGISTRY_PUSH(registry, fld, it) do { \
+       it.fld = registry##_COUNT; \
+       _R_SET(_##registry, registry##_COUNT, it); \
+       ++registry##_COUNT; \
+       if (!registry##_first) registry##_first = it; \
+       if (registry##_last)   registry##_last.REGISTRY_NEXT = it; \
+       registry##_last = it; \
+} while (0)
+
+#define REGISTRY_RESERVE(registry, fld, id, suffix) do { \
+       entity e = new(registry_reserved); \
+       make_pure(e); \
+       e.registered_id = #id "/" #suffix; \
+       REGISTRY_PUSH(registry, fld, e); \
+} while (0)
+
 #define REGISTER_INIT(id) [[accumulate]] void Register_##id##_init(entity this)
 #define REGISTER_INIT_POST(id) [[accumulate]] void Register_##id##_init_post(entity this)
 
index 12dc425cd356e876a78e3406d4cb58126a6ea4d8..da796b910f5fd69745323de0b3493e7530ea5843 100644 (file)
@@ -1,11 +1,15 @@
 #ifndef LIB_STATS_H
 #define LIB_STATS_H
 
+// TODO: rename to 'netvars'
+
 #include "registry.qh"
 #include "sort.qh"
 
 .int m_id;
+typedef vector vectori;
 
+#define REGISTER_STAT(...) EVAL(OVERLOAD(REGISTER_STAT, __VA_ARGS__))
 #if defined(CSQC)
        /** Get all stats and store them as globals, access with `STAT(ID)` */
        void stats_get() {}
        #define getstat_int(id) getstati(id, 0, 24)
        #define getstat_bool(id) boolean(getstati(id))
        #define getstat_float(id) getstatf(id)
+       #define getstat_vector(id) vec3(getstat_float(id + 0), getstat_float(id + 1), getstat_float(id + 2))
+       #define getstat_vectori(id) vec3(getstat_int(id + 0), getstat_int(id + 1), getstat_int(id + 2))
 
        #define _STAT(id) g_stat_##id
-       #define REGISTER_STAT(id, type) \
-               type _STAT(id); \
-               REGISTER(Stats, STATid, m_id, new(stat)) \
+       #define REGISTER_STAT_2(id, T) \
+               T _STAT(id); \
+               REGISTER(Stats, STAT_##id, m_id, new(stat)) \
                { \
                        make_pure(this); \
+                       if (#T == "vector" || #T == "vectori") { \
+                               REGISTRY_RESERVE(Stats, m_id, STAT_##id, y); \
+                               REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
+                       } \
                } \
                [[accumulate]] void stats_get() \
                { \
-                       _STAT(id) = getstat_##type(STAT_##id.m_id); \
+                       _STAT(id) = getstat_##T(STAT_##id.m_id); \
                }
+       #define REGISTER_STAT_3(x, T, expr) REGISTER_STAT(x, T)
 #elif defined(SVQC)
        /** Add all registered stats, access with `STAT(ID, player)` or `.type stat = _STAT(ID); player.stat` */
        void stats_add() {}
        #define addstat_int(id, fld) addstat(id, AS_INT, fld)
        #define addstat_bool(id, fld) addstat(id, AS_INT, fld)
        #define addstat_float(id, fld) addstat(id, AS_FLOAT, fld)
+       #define addstat_vector(id, fld) do { \
+               addstat_float(id + 0, fld##_x); \
+               addstat_float(id + 1, fld##_y); \
+               addstat_float(id + 2, fld##_z); \
+       } while (0)
+       #define addstat_vectori(id, fld) do { \
+               addstat_int(id + 0, fld##_x); \
+               addstat_int(id + 1, fld##_y); \
+               addstat_int(id + 2, fld##_z); \
+       } while (0)
        const int AS_STRING = 1;
        const int AS_INT = 2;
        const int AS_FLOAT = 8;
 
+       .int __stat_null;
+       /** Prevent engine stats being sent */
+       STATIC_INIT(stats_clear)
+       {
+               int r = 32;
+               for (int i = 0, n = 256 - r; i < n; ++i) {
+                       addstat(r + i, AS_INT, __stat_null);
+               }
+       }
+
        #define _STAT(id) stat_##id
-       #define REGISTER_STAT(id, type) \
-               .type _STAT(id); \
-               REGISTER(Stats, STATid, m_id, new(stat)) \
+       #define REGISTER_STAT_2(id, T) \
+               .T _STAT(id); \
+               REGISTER(Stats, STAT_##id, m_id, new(stat)) \
                { \
                        make_pure(this); \
+                       if (#T == "vector" || #T == "vectori") { \
+                               REGISTRY_RESERVE(Stats, m_id, STAT_##id, y); \
+                               REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
+                       } \
                } \
                [[accumulate]] void stats_add() \
                { \
-                       addstat_##type(STAT_##id.m_id, _STAT(id)); \
+                       addstat_##T(STAT_##id.m_id, _STAT(id)); \
                }
+       void GlobalStats_update(entity this) {}
+    #define REGISTER_STAT_3(x, T, expr) \
+       REGISTER_STAT(x, T); \
+       [[accumulate]] void GlobalStats_update(entity this) { STAT(x, this) = (expr); } \
+       STATIC_INIT(worldstat_##x) { entity this = world; STAT(x, this) = (expr); }
 #else
-       #define REGISTER_STAT(id, type)
+       #define REGISTER_STAT_2(id, type)
+    #define REGISTER_STAT_3(x, T, expr)
 #endif
 
-const int STATS_ENGINE_RESERVE = 32 + (8 * 3); // Not sure how to handle vector stats yet, reserve them too
+const int STATS_ENGINE_RESERVE = 32;
 
-REGISTRY(Stats, 220 - STATS_ENGINE_RESERVE)
+REGISTRY(Stats, 256 - STATS_ENGINE_RESERVE)
 REGISTER_REGISTRY(Stats)
 REGISTRY_SORT(Stats)
 REGISTRY_CHECK(Stats)
diff --git a/qcsrc/lib/unsafe.qh b/qcsrc/lib/unsafe.qh
new file mode 100644 (file)
index 0000000..f8fa382
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef UNSAFE_H
+#define UNSAFE_H
+
+#define reinterpret_cast(T, it) _unsafe_cast_##T(0, it)
+#define X(T) T _unsafe_cast_##T(int dummy, ...) { return ...(0, T); }
+X(float)
+X(entity)
+X(string)
+typedef float(...) rawfunc;
+X(rawfunc)
+#undef X
+
+#define strid(s) etof(reinterpret_cast(entity, s))
+
+#endif
index d6eee7aceae92104220446b7ee56659daa79c9b0..ec8257e3a672ce72d5007689208111fe2d2ca44d 100644 (file)
@@ -67,6 +67,16 @@ float boxesoverlap(vector m1, vector m2, vector m3, vector m4) { return m2_x >=
 /** requires the same as boxesoverlap, but is a stronger condition */
 float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) { return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z; }
 
+#define PITCH(v) ((v).x)
+#define YAW(v) ((v).y)
+#define ROLL(v) ((v).z)
+
+#define MAKEVECTORS(f, angles, forward, right, up) do { \
+       f(angles); \
+       forward = v_forward; \
+       right = v_right; \
+       up = v_up; \
+} while (0)
 
 noref vector _vec2;
 #define vec2(v) (_vec2 = (v), _vec2.z = 0, _vec2)
index dd2b5cc9a115b2d606e5dfffc05480ac31940d7d..e33a72b1ed9830403468e61e27f251cba3708094 100644 (file)
@@ -25,6 +25,7 @@ void WarpZone_Fade_PreDraw()
                self.drawmask = MASK_NORMAL;
 }
 
+void WarpZone_Touch ();
 NET_HANDLE(ENT_CLIENT_WARPZONE, bool isnew)
 {
        warpzone_warpzones_exist = 1;
@@ -87,6 +88,8 @@ NET_HANDLE(ENT_CLIENT_WARPZONE, bool isnew)
        // how to draw
        // engine currently wants this
        self.predraw = WarpZone_Fade_PreDraw;
+
+       //self.move_touch = WarpZone_Touch;
        return true;
 }
 
index 342bc0c5a92ae4f1c7f682ce691254d97e6b8743..b97d58ca0cbe337925bfe7655d8a87c60f862ace 100644 (file)
 
 void WarpZone_StoreProjectileData(entity e)
 {
+#ifdef SVQC
        e.warpzone_oldorigin = e.origin;
        e.warpzone_oldvelocity = e.velocity;
        e.warpzone_oldangles = e.angles;
+#elif defined(CSQC)
+       e.warpzone_oldorigin = e.move_origin;
+       e.warpzone_oldvelocity = e.move_velocity;
+       e.warpzone_oldangles = e.move_angles;
+#endif
 }
 
 void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity)
 {
+#ifdef SVQC
        setorigin (player, to); // NOTE: this also aborts the move, when this is called by touch
        player.oldorigin = to; // for DP's unsticking
        player.angles = to_angles;
        player.fixangle = true;
        player.velocity = to_velocity;
+#elif defined(CSQC)
+       player.move_origin = to;
+       player.move_angles = to_angles;
+       player.move_velocity = to_velocity;
+#endif
 
        BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
 
        if(IS_PLAYER(player))
+#ifdef SVQC
                BITCLR_ASSIGN(player.flags, FL_ONGROUND);
+#elif defined(CSQC)
+               BITCLR_ASSIGN(player.move_flags, FL_ONGROUND);
+#endif
 
        WarpZone_PostTeleportPlayer_Callback(player);
 }
 
+#ifdef SVQC
 bool WarpZone_Teleported_Send(entity to, int sf)
 {SELFPARAM();
        WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
@@ -59,19 +76,26 @@ bool WarpZone_Teleported_Send(entity to, int sf)
        WriteCoord(MSG_ENTITY, self.angles.z);
        return true;
 }
+#endif
 
 float WarpZone_Teleport(entity wz, entity player, float f0, float f1)
 {
        vector o0, a0, v0, o1, a1, v1, o10;
 
+#ifdef SVQC
        o0 = player.origin + player.view_ofs;
        v0 = player.velocity;
        a0 = player.angles;
+#elif defined(CSQC)
+       o0 = player.move_origin + player.view_ofs;
+       v0 = player.move_velocity;
+       a0 = player.move_angles;
+#endif
 
        o10 = o1 = WarpZone_TransformOrigin(wz, o0);
        v1 = WarpZone_TransformVelocity(wz, v0);
        if (!IS_NOT_A_CLIENT(player))
-               a1 = WarpZone_TransformVAngles(wz, player.v_angle);
+               a1 = WarpZone_TransformVAngles(wz, PHYS_INPUT_ANGLES(player));
        else
                a1 = WarpZone_TransformAngles(wz, a0);
 
@@ -124,12 +148,15 @@ float WarpZone_Teleport(entity wz, entity player, float f0, float f1)
        player.warpzone_teleport_finishtime = time;
        player.warpzone_teleport_zone = wz;
 
+#ifdef SVQC
        // prevent further teleports back
        float dt = (o1 - o10) * v1 * (1 / (v1 * v1));
-       if(dt < sys_frametime)
-               player.warpzone_teleport_finishtime += sys_frametime - dt;
+       if(dt < PHYS_INPUT_FRAMETIME)
+               player.warpzone_teleport_finishtime += PHYS_INPUT_FRAMETIME - dt;
+#endif
 
 #ifndef WARPZONE_USE_FIXANGLE
+       #ifdef SVQC
        if(IS_VEHICLE(player) && player.owner)
                player = player.owner; // hax
        if(IS_PLAYER(player))
@@ -149,6 +176,11 @@ float WarpZone_Teleport(entity wz, entity player, float f0, float f1)
                ts.effects = EF_NODEPTHTEST;
                ts.angles = wz.warpzone_transform;
        }
+       #elif defined(CSQC)
+       setproperty(VF_CL_VIEWANGLES, WarpZone_TransformVAngles(wz, getpropertyvec(VF_CL_VIEWANGLES)));
+       //if(checkextension("DP_CSQC_ROTATEMOVES"))
+               //CL_RotateMoves(wz.warpzone_transform);
+       #endif
 #endif
 
        return 1;
@@ -163,13 +195,21 @@ void WarpZone_Touch ()
                return;
 
        // FIXME needs a better check to know what is safe to teleport and what not
+#ifdef SVQC
        if(other.movetype == MOVETYPE_NONE || other.movetype == MOVETYPE_FOLLOW || other.tag_entity)
+#elif defined(CSQC)
+       if(other.move_movetype == MOVETYPE_NONE || other.move_movetype == MOVETYPE_FOLLOW || other.tag_networkentity)
+#endif
                return;
 
        if(WarpZoneLib_ExactTrigger_Touch())
                return;
 
+#ifdef SVQC
        if(WarpZone_PlaneDist(self, other.origin + other.view_ofs) >= 0) // wrong side of the trigger_warpzone (don't teleport yet)
+#elif defined(CSQC)
+       if(WarpZone_PlaneDist(self, other.move_origin + other.view_ofs) >= 0) // wrong side of the trigger_warpzone (don't teleport yet)
+#endif
                return;
 
        float f;
@@ -186,11 +226,16 @@ void WarpZone_Touch ()
        float d;
        d = 24 + max(vlen(other.mins), vlen(other.maxs));
        if(IS_NOT_A_CLIENT(other))
+       #ifdef SVQC
                f = -d / bound(frametime * d * 1, frametime * vlen(other.velocity), d);
+       #elif defined(CSQC)
+               f = -d / bound(frametime * d * 1, frametime * vlen(other.move_velocity), d);
+       #endif
        else
                f = -1;
        if(WarpZone_Teleport(self, other, f, 0))
        {
+#ifdef SVQC
                string save1, save2;
                activator = other;
 
@@ -207,6 +252,7 @@ void WarpZone_Touch ()
                if (!self.target) self.target = save1;
                if (!self.target2) self.target2 = save2;
                setself(this);
+#endif
        }
        else
        {
@@ -214,6 +260,7 @@ void WarpZone_Touch ()
        }
 }
 
+#ifdef SVQC
 bool WarpZone_Send(entity to, int sendflags)
 {SELFPARAM();
        WriteHeader(MSG_ENTITY, ENT_CLIENT_WARPZONE);
@@ -318,8 +365,17 @@ float WarpZone_CheckProjectileImpact(entity player)
 {SELFPARAM();
        vector o0, v0;
 
-       o0 = player.origin + player.view_ofs;
-       v0 = player.velocity;
+       .vector orgvec, velvec;
+#ifdef SVQC
+       orgvec = origin;
+       velvec = velocity;
+#elif defined(CSQC)
+       orgvec = move_origin;
+       velvec = move_velocity;
+#endif
+
+       o0 = player.orgvec + player.view_ofs;
+       v0 = player.velvec;
 
        // if we teleported shortly before, abort
        if(time <= player.warpzone_teleport_finishtime + 0.1)
@@ -337,15 +393,19 @@ float WarpZone_CheckProjectileImpact(entity player)
        LOG_INFO("impactfilter found something - and it even gets handled correctly - please tell divVerent that this code apparently gets triggered again\n");
 #endif
        LOG_INFO("Entity type: ", player.classname, "\n");
-       LOG_INFO("Origin: ", vtos(player.origin), "\n");
-       LOG_INFO("Velocity: ", vtos(player.velocity), "\n");
+       LOG_INFO("Origin: ", vtos(player.orgvec), "\n");
+       LOG_INFO("Velocity: ", vtos(player.velvec), "\n");
 
 #ifdef WARPZONELIB_REMOVEHACK
        return 0;
 #else
        // retry previous move
+#ifdef SVQC
        setorigin(player, player.warpzone_oldorigin);
-       player.velocity = player.warpzone_oldvelocity;
+#elif defined(CSQC)
+       player.move_origin = player.warpzone_oldorigin;
+#endif
+       player.velvec = player.warpzone_oldvelocity;
        if(WarpZone_Teleport(wz, player, 0, 1))
        {
                entity oldself;
@@ -373,13 +433,14 @@ float WarpZone_CheckProjectileImpact(entity player)
        else
        {
                setorigin(player, o0 - player.view_ofs);
-               player.velocity = v0;
+               player.velvec = v0;
        }
 
        return +1;
 #endif
 }
 #endif
+#endif
 
 float WarpZone_Projectile_Touch()
 {SELFPARAM();
@@ -395,6 +456,7 @@ float WarpZone_Projectile_Touch()
        if(time == self.warpzone_teleport_time)
                return true;
 
+#ifdef SVQC
 #ifdef WARPZONELIB_KEEPDEBUG
        // this SEEMS to not happen at the moment, but if it did, it would be more reliable
        {
@@ -445,10 +507,13 @@ float WarpZone_Projectile_Touch()
 
        if(WarpZone_Projectile_Touch_ImpactFilter_Callback())
                return true;
+#endif
 
        return false;
 }
 
+#ifdef SVQC
+
 void WarpZone_InitStep_FindOriginTarget()
 {SELFPARAM();
        if(self.killtarget != "")
@@ -892,3 +957,5 @@ void WarpZone_PlayerPhysics_FixVAngle()
        }
 #endif
 }
+
+#endif
index b96b7b3361e3d3c6ce12c063fa27839d2052d384..0e0594a1ba403d0ea422a6e8a66a9f9e8a464ae7 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef LIB_WARPZONE_SERVER_H
 #define LIB_WARPZONE_SERVER_H
 
+#ifdef SVQC
 void WarpZone_StartFrame();
 float WarpZone_Projectile_Touch();
 
@@ -16,3 +17,5 @@ void WarpZone_PlayerPhysics_FixVAngle();
 
 void WarpZone_PostInitialize_Callback();
 #endif
+
+#endif
index 46f7f9a9171f3eba41160375fce1fc9890d05f21..eedb59ecaf2c5a88e94c9b4db36120752a79417b 100644 (file)
@@ -72,7 +72,7 @@ void GameCommand(string theCommand)
        if (argv(0) == "directmenu" || argv(0) == "directpanelhudmenu")
        {
                string filter = string_null;
-               if (argv(0) == "directpanelhudmenu") filter = strzone("HUD");
+               if (argv(0) == "directpanelhudmenu") filter = "HUD";
 
                if (argc == 1)
                {
@@ -94,7 +94,6 @@ void GameCommand(string theCommand)
                        m_play_click_sound(MENU_SOUND_OPEN);
                        m_goto(strcat(filter, argv(1))); // switch to a menu item
                }
-               if (filter) strunzone(filter);
                return;
        }
 
index eff3723bd46e6315bb6a5d0495776cff77a06312..5123394bfc79b46f2544e06cf0fca07db3e80401 100644 (file)
@@ -53,7 +53,7 @@ string WeaponArenaString()
        {
                for(j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       e = get_weaponinfo(j);
+                       e = Weapons_from(j);
                        if(argv(i) == e.netname)
                                s = strcat(s, " & ", e.m_name);
                }
@@ -254,7 +254,7 @@ void XonoticMutatorsDialog_fill(entity me)
                        e.cvarOffValue = "0";
        for(i = WEP_FIRST, j = 0; i <= WEP_LAST; ++i)
        {
-               w = get_weaponinfo(i);
+               w = Weapons_from(i);
                if(w.spawnflags & WEP_FLAG_HIDDEN)
                        continue;
                if((j & 1) == 0)
index 1c0bf3563c69b8e375fb90e58cd7b21fedeb6d76..039cb5a15fbce6aa198a8f010ddaa5ae4d41d815 100644 (file)
@@ -81,26 +81,21 @@ void Xonotic_KeyBinds_Read()
 
        int i;
 
-       #define ADD_TO_W_LIST(pred) do { \
-               for(i = WEP_FIRST; i <= WEP_LAST; ++i) \
-               { \
-                       wep = get_weaponinfo(i); \
-                       if(wep.impulse == imp && (pred)) \
-                               w_list = strcat(w_list, WEP_NAME(i), " / "); \
-               } \
-       } while(0)
-
-       int imp;
-       entity wep;
-       string w_list = "";
-       for(imp = 1; imp <= 9; ++imp)
+       #define ADD_TO_W_LIST(pred) \
+               FOREACH(Weapons, it != WEP_Null, LAMBDA( \
+                       if (it.impulse != imp) continue; \
+                       if (!(pred)) continue; \
+                       w_list = strcat(w_list, it.m_name, " / "); \
+               ))
+
+       for(int imp = 1; imp <= 9; ++imp)
        {
-               ADD_TO_W_LIST(!(wep.flags & WEP_FLAG_MUTATORBLOCKED) && !(wep.flags & WEP_FLAG_SUPERWEAPON));
-               ADD_TO_W_LIST(wep.flags & WEP_FLAG_SUPERWEAPON);
-               ADD_TO_W_LIST(wep.flags & WEP_FLAG_MUTATORBLOCKED);
+        string w_list = "";
+               ADD_TO_W_LIST(!(it.flags & WEP_FLAG_MUTATORBLOCKED) && !(it.flags & WEP_FLAG_SUPERWEAPON));
+               ADD_TO_W_LIST(it.flags & WEP_FLAG_SUPERWEAPON);
+               ADD_TO_W_LIST(it.flags & WEP_FLAG_MUTATORBLOCKED);
                if(w_list)
                        KEYBIND_DEF(strcat("weapon_group_", itos(imp)), substring(w_list, 0, -4));
-               w_list = "";
                if(imp == 0)
                        break;
                if(imp == 9)
index 1450e8ff78e020033032b1dfa59a4d314e2aec8f..5bfdb8d63b7d11873409bfc17324b0ed772beb08 100644 (file)
@@ -177,7 +177,7 @@ void RegisterSLCategories()
                SET_FIELD_COUNT(name, CATEGORY_FIRST, category_ent_count) \
                CHECK_MAX_COUNT(name, MAX_CATEGORIES, category_ent_count, "SLIST_CATEGORY") \
                cat = categories[name - 1] = new(slist_category); \
-               cat.cat_name = strzone(#name); \
+               cat.cat_name = #name; \
                cat.cat_enoverride_string = strzone(SLIST_CATEGORY_AUTOCVAR(name)); \
                cat.cat_dioverride_string = strzone(dioverride); \
                cat.cat_string = strzone(str);
@@ -202,6 +202,7 @@ void RegisterSLCategories()
                                if(catnum) \
                                { \
                                        strunzone(categories[i].override_string); \
+                                       categories[i].override_string = string_null; \
                                        categories[i].override_field = catnum; \
                                        continue; \
                                } \
@@ -215,6 +216,7 @@ void RegisterSLCategories()
                                } \
                        } \
                        strunzone(categories[i].override_string); \
+                       categories[i].override_string = string_null; \
                        categories[i].override_field = 0; \
                }
        PROCESS_OVERRIDE(cat_enoverride_string, cat_enoverride)
index c1189dd9ba5c702214c50c0ecea30e4613f713b7..8a3fbd670e669d42640e1864a917f481f4f5ac7f 100644 (file)
@@ -87,7 +87,7 @@ string XonoticWeaponsList_toString(entity me)
        s = "";
        for(i = 0; i < n; ++i)
        {
-               e = get_weaponinfo(stof(argv(i)));
+               e = Weapons_from(stof(argv(i)));
                s = strcat(s, e.m_name, ", ");
        }
        return substring(s, 0, strlen(s) - 2);
@@ -102,7 +102,7 @@ void XonoticWeaponsList_drawListBoxItem(entity me, int i, vector absSize, bool i
                me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
                draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
        }
-       e = get_weaponinfo(stof(argv(i)));
+       e = Weapons_from(stof(argv(i)));
        string msg = e.m_name;
        if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
                msg = strcat(msg, "*");
index cb48688f6216768f10e454d4c76996133bdc7bbb..e4220f5d0c7f174d39befa55a55bd9f3710cc8b9 100644 (file)
@@ -296,13 +296,6 @@ bool autocvar_g_use_ammunition;
 bool autocvar_g_waypointeditor;
 int autocvar_g_waypointeditor_auto;
 bool autocvar_g_waypoints_for_items;
-float autocvar_g_weapon_charge_colormod_blue_full;
-float autocvar_g_weapon_charge_colormod_blue_half;
-float autocvar_g_weapon_charge_colormod_green_full;
-float autocvar_g_weapon_charge_colormod_green_half;
-float autocvar_g_weapon_charge_colormod_hdrmultiplier;
-float autocvar_g_weapon_charge_colormod_red_full;
-float autocvar_g_weapon_charge_colormod_red_half;
 #define autocvar_g_weapon_stay cvar("g_weapon_stay")
 bool autocvar_g_weapon_throwable;
 #define autocvar_g_weaponarena cvar_string("g_weaponarena")
@@ -347,7 +340,7 @@ string autocvar_sv_defaultplayermodel_pink;
 string autocvar_sv_defaultplayermodel_red;
 string autocvar_sv_defaultplayermodel_yellow;
 int autocvar_sv_defaultplayerskin;
-bool autocvar_sv_dodging_frozen;
+bool autocvar_sv_doublejump;
 bool autocvar_sv_eventlog;
 bool autocvar_sv_eventlog_console;
 bool autocvar_sv_eventlog_files;
index dd0109ce2fba337275eec28b6eebf69ce9a2a74d..9a74d38415aa6b545fcb646b8f1ed25da238be0b 100644 (file)
@@ -104,7 +104,7 @@ void havocbot_ai()
 
                if(self.weapons)
                {
-                       Weapon w = get_weaponinfo(self.weapon);
+                       Weapon w = Weapons_from(self.weapon);
                        w.wr_aim(w);
                        if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self))
                        {
@@ -173,7 +173,7 @@ void havocbot_ai()
                {
                        for (int i = WEP_FIRST; i <= WEP_LAST; ++i)
                        {
-                               entity e = get_weaponinfo(i);
+                               entity e = Weapons_from(i);
                                if ((self.weapons & (e.m_wepset)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < e.reloading_ammo))
                                        self.switchweapon = i;
                        }
@@ -995,7 +995,7 @@ float havocbot_chooseweapon_checkreload(int new_weapon)
                float i, other_weapon_available = false;
                for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                {
-                       Weapon w = get_weaponinfo(i);
+                       Weapon w = Weapons_from(i);
                        // if we are out of ammo for all other weapons, it's an emergency to switch to anything else
                        if (w.wr_checkammo1(w) + w.wr_checkammo2(w))
                                other_weapon_available = true;
index fbe028eaffec5518efa0828cf09cc88428c80d6c..c9d178720f95bca81fb9626ac2b60c0cee9c5658 100644 (file)
@@ -963,6 +963,8 @@ void FixClientCvars(entity e)
                stuffcmd(e, "cl_cmd settemp cl_prydoncursor_notrace 0\n");
        if(autocvar_sv_gentle)
                stuffcmd(e, "cl_cmd settemp cl_gentle 1\n");
+
+       MUTATOR_CALLHOOK(FixClientCvars, e);
 }
 
 float PlayerInIDList(entity p, string idlist)
@@ -1664,8 +1666,8 @@ spectate mode routines
 ======================
 */
 
-void SpectateCopy(entity spectatee)
-{SELFPARAM();
+void SpectateCopy(entity this, entity spectatee)
+{
        MUTATOR_CALLHOOK(SpectateCopy, spectatee, self);
        self.armortype = spectatee.armortype;
        self.armorvalue = spectatee.armorvalue;
@@ -1750,7 +1752,7 @@ bool SpectateUpdate()
                return false;
        }
 
-       SpectateCopy(self.enemy);
+       SpectateCopy(this, this.enemy);
 
        return true;
 }
@@ -2322,22 +2324,6 @@ void PlayerPreThink ()
 
                if(frametime)
                {
-                       if(self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge))
-                       {
-                               self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
-                               self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
-                               self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
-
-                               if(self.vortex_charge > WEP_CVAR(vortex, charge_animlimit))
-                               {
-                                       self.weaponentity_glowmod_x = self.weaponentity_glowmod.x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
-                                       self.weaponentity_glowmod_y = self.weaponentity_glowmod.y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
-                                       self.weaponentity_glowmod_z = self.weaponentity_glowmod.z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
-                               }
-                       }
-                       else
-                               self.weaponentity_glowmod = colormapPaletteColor(self.clientcolors & 0x0F, true) * 2;
-
                        player_powerups();
                }
 
@@ -2427,8 +2413,8 @@ void PlayerPreThink ()
                        if (!self.crouch)
                        {
                                self.crouch = true;
-                               self.view_ofs = self.stat_pl_crouch_view_ofs;
-                               setsize (self, self.stat_pl_crouch_min, self.stat_pl_crouch_max);
+                               self.view_ofs = STAT(PL_CROUCH_VIEW_OFS, self);
+                               setsize (self, STAT(PL_CROUCH_MIN, self), STAT(PL_CROUCH_MAX, self));
                                // setanim(self, self.anim_duck, false, true, true); // this anim is BROKEN anyway
                        }
                }
@@ -2436,12 +2422,12 @@ void PlayerPreThink ()
                {
                        if (self.crouch)
                        {
-                               tracebox(self.origin, self.stat_pl_min, self.stat_pl_max, self.origin, false, self);
+                               tracebox(self.origin, STAT(PL_MIN, self), STAT(PL_MAX, self), self.origin, false, self);
                                if (!trace_startsolid)
                                {
                                        self.crouch = false;
-                                       self.view_ofs = self.stat_pl_view_ofs;
-                                       setsize (self, self.stat_pl_min, self.stat_pl_max);
+                                       self.view_ofs = STAT(PL_VIEW_OFS, self);
+                                       setsize (self, STAT(PL_MIN, self), STAT(PL_MAX, self));
                                }
                        }
                }
@@ -2507,6 +2493,8 @@ void PlayerPreThink ()
        if(self.spectatee_status != oldspectatee_status)
        {
                ClientData_Touch(self);
+               if(g_race || g_cts)
+                       race_InitSpectator();
        }
 
        if(self.teamkill_soundtime)
@@ -2514,21 +2502,18 @@ void PlayerPreThink ()
        {
                self.teamkill_soundtime = 0;
 
-               setself(self.teamkill_soundsource);
-               entity oldpusher = self.pusher;
-               self.pusher = this;
-
-               PlayerSound(playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
-
-               self.pusher = oldpusher;
-               setself(this);
+               entity e = self.teamkill_soundsource;
+               entity oldpusher = e.pusher;
+               e.pusher = this;
+               PlayerSound(e, playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
+               e.pusher = oldpusher;
        }
 
        if(self.taunt_soundtime)
        if(time > self.taunt_soundtime)
        {
                self.taunt_soundtime = 0;
-               PlayerSound(playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT);
+               PlayerSound(self, playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT);
        }
 
        target_voicescript_next(self);
@@ -2539,6 +2524,28 @@ void PlayerPreThink ()
                self.clip_load = self.clip_size = 0;
 }
 
+void DrownPlayer(entity this)
+{
+       if(this.deadflag != DEAD_NO)
+               return;
+
+       if (this.waterlevel != WATERLEVEL_SUBMERGED)
+       {
+               if(this.air_finished < time)
+                       PlayerSound(this, playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+               this.air_finished = time + autocvar_g_balance_contents_drowndelay;
+               this.dmg = 2;
+       }
+       else if (this.air_finished < time)
+       {       // drown!
+               if (this.pain_finished < time)
+               {
+                       Damage (this, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, this.origin, '0 0 0');
+                       this.pain_finished = time + 0.5;
+               }
+       }
+}
+
 /*
 =============
 PlayerPostThink
@@ -2590,6 +2597,7 @@ void PlayerPostThink ()
        //CheckPlayerJump();
 
        if(IS_PLAYER(self)) {
+               DrownPlayer(self);
                CheckRules_Player();
                UpdateChatBubble();
                if (self.impulse)
index 1b462a329538ab3c6527a43b187a08f416d28804..a0dfd72f8218722b3c8858e71a8b7b3c3f7bb5c5 100644 (file)
@@ -8,4 +8,6 @@ float CalcRotRegen(float current, float regenstable, float regenfactor, float re
 
 float Spectate(entity pl);
 
+#define SPECTATE_COPY(fld) [[accumulate]] void SpectateCopy(entity this, entity spectatee) { this.(fld) = spectatee.(fld); }
+
 #endif
index ab5ad3b527be7dcd27d2c162e9ce7ec11803fa26..05cd17d0d99a9dc9b8d8e564c62e66fc7fe6ef71 100644 (file)
@@ -139,7 +139,7 @@ void ImpulseCommands ()
                                        break;
                                case 20:
                                        if(!forbidWeaponUse(self)) {
-                                               Weapon w = get_weaponinfo(self.weapon);
+                                               Weapon w = Weapons_from(self.weapon);
                                                w.wr_reload(w);
                                        }
                                        break;
index a9a5d03cbe2e93965f73b25e603cfbc31a5f5288..d7ce1f66aedd85785d6f95b62416b4456e37f66f 100644 (file)
@@ -9,6 +9,7 @@
 #include "teamplay.qh"
 #include "weapons/throwing.qh"
 #include "command/common.qh"
+#include "../common/anim.qh"
 #include "../common/animdecide.qh"
 #include "../common/csqcmodel_settings.qh"
 #include "../common/deathtypes/all.qh"
@@ -154,16 +155,6 @@ void player_anim ()
                animbits |= ANIMSTATE_DUCK;
        animdecide_setstate(self, animbits, false);
        animdecide_setimplicitstate(self, (self.flags & FL_ONGROUND));
-
-       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
-       {
-               if (self.(weaponentity))
-               {
-                       updateanim(self.(weaponentity));
-                       if (!self.(weaponentity).animstate_override)
-                               setanim(self.(weaponentity), self.(weaponentity).anim_idle, true, false, false);
-               }
-       }
 }
 
 void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
@@ -439,15 +430,15 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp
                                        // exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two
                                        {
                                                if(deathtype == DEATH_FALL.m_id)
-                                                       PlayerSound(playersound_fall, CH_PAIN, VOICETYPE_PLAYERSOUND);
+                                                       PlayerSound(self, playersound_fall, CH_PAIN, VOICETYPE_PLAYERSOUND);
                                                else if(self.health > 75) // TODO make a "gentle" version?
-                                                       PlayerSound(playersound_pain100, CH_PAIN, VOICETYPE_PLAYERSOUND);
+                                                       PlayerSound(self, playersound_pain100, CH_PAIN, VOICETYPE_PLAYERSOUND);
                                                else if(self.health > 50)
-                                                       PlayerSound(playersound_pain75, CH_PAIN, VOICETYPE_PLAYERSOUND);
+                                                       PlayerSound(self, playersound_pain75, CH_PAIN, VOICETYPE_PLAYERSOUND);
                                                else if(self.health > 25)
-                                                       PlayerSound(playersound_pain50, CH_PAIN, VOICETYPE_PLAYERSOUND);
+                                                       PlayerSound(self, playersound_pain50, CH_PAIN, VOICETYPE_PLAYERSOUND);
                                                else
-                                                       PlayerSound(playersound_pain25, CH_PAIN, VOICETYPE_PLAYERSOUND);
+                                                       PlayerSound(self, playersound_pain25, CH_PAIN, VOICETYPE_PLAYERSOUND);
                                        }
                                }
                        }
@@ -491,7 +482,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp
        if(DIFF_TEAM(self, attacker))
        {
                if(DEATH_ISSPECIAL(deathtype))
-                       awep = get_weaponinfo(attacker.weapon);
+                       awep = Weapons_from(attacker.weapon);
                else
                        awep = DEATH_WEAPONOF(deathtype);
                valid_damage_for_weaponstats = 1;
@@ -523,9 +514,9 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp
                if(sound_allowed(MSG_BROADCAST, attacker))
                {
                        if(deathtype == DEATH_DROWN.m_id)
-                               PlayerSound(playersound_drown, CH_PAIN, VOICETYPE_PLAYERSOUND);
+                               PlayerSound(self, playersound_drown, CH_PAIN, VOICETYPE_PLAYERSOUND);
                        else
-                               PlayerSound(playersound_death, CH_PAIN, VOICETYPE_PLAYERSOUND);
+                               PlayerSound(self, playersound_death, CH_PAIN, VOICETYPE_PLAYERSOUND);
                }
 
                // get rid of kill indicator
@@ -557,7 +548,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp
                MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, self, deathtype);
                excess = frag_damage;
 
-               Weapon wep = get_weaponinfo(self.weapon);
+               Weapon wep = Weapons_from(self.weapon);
                wep.wr_playerdeath(wep);
 
                RemoveGrapplingHook(self);
@@ -640,7 +631,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp
                // reset fields the weapons may use just in case
                for (j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       Weapon w = get_weaponinfo(j);
+                       Weapon w = Weapons_from(j);
                        w.wr_resetplayer(w);
                        for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                        {
index 6cac1c4f0620fb5a224e6d8dd2c0a5a39a865873..573b9417f99f887859b34243b515c8c5ced79224 100644 (file)
@@ -607,8 +607,8 @@ void ClientCommand_voice(float request, float argc, string command)
                                        sprint(this, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
                                        return;
                                }
-                               if (argc >= 3) VoiceMessage(e, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
-                               else VoiceMessage(e, "");
+                               if (argc >= 3) VoiceMessage(this, e, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
+                               else VoiceMessage(this, e, "");
 
                                return;
                        }
index c04acac1593aa6bb8880c9ea77bf96d2b0ffcc64..62fec55feee4890ecd8b100eaa9b51ebb38ff5af 100644 (file)
@@ -77,7 +77,7 @@ float server_is_dedicated;
 
 .float strength_finished = _STAT(STRENGTH_FINISHED);
 .float invincible_finished = _STAT(INVINCIBLE_FINISHED);
-.float superweapons_finished;
+.float superweapons_finished = _STAT(SUPERWEAPONS_FINISHED);
 
 .float cnt; // used in too many places
 .float count;
@@ -91,14 +91,7 @@ float server_is_dedicated;
 .float fade_time;
 .float fade_rate;
 
-// weapon animation vectors:
-.vector anim_fire1;
-.vector anim_fire2;
-.vector anim_idle;
-.vector anim_reload;
-
 void() player_setupanimsformodel;
-void setanim(entity e, vector anim, float looping, float override, float restart);
 
 .string mdl;
 
@@ -149,16 +142,6 @@ const float MAX_DAMAGEEXTRARADIUS = 16;
 .entity item_pickupsound_ent;
 .entity item_model_ent;
 
-// definitions for weaponsystem
-// more WEAPONTODO: move these to their proper files
-.entity exteriorweaponentity;
-.vector weaponentity_glowmod;
-
-//.int weapon; // current weapon
-.int switchweapon = _STAT(SWITCHWEAPON);
-.int switchingweapon; // weapon currently being switched to (is copied from switchweapon once switch is possible)
-.string weaponname; // name of .weapon
-
 // WEAPONTODO
 .float autoswitch;
 float client_hasweapon(entity cl, float wpn, float andammo, float complain);
@@ -169,13 +152,6 @@ void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire);
 .void(Weapon thiswep, entity actor, .entity weaponentity, int fire) weapon_think;
 
 
-// weapon states (self.weaponentity.state)
-const int WS_CLEAR                     = 0; // no weapon selected
-const int WS_RAISE                     = 1; // raise frame
-const int WS_DROP                              = 2; // deselecting frame
-const int WS_INUSE                     = 3; // fire state
-const int WS_READY                     = 4; // idle frame
-
 // there is 2 weapon tics that can run in one server frame
 const int W_TICSPERFRAME = 2;
 
@@ -212,8 +188,6 @@ float nJoinAllowed(entity ignore);
 float playerid_last;
 .float noalign;                // if set to 1, the item or spawnpoint won't be dropped to the floor
 
-.vector spawnorigin;
-
 .vector death_origin;
 .vector killer_origin;
 
@@ -225,7 +199,7 @@ float default_weapon_alpha;
 .float cvar_cl_clippedspectating;
 .float cvar_cl_autoscreenshot;
 .float cvar_cl_jetpack_jump;
-.float cvar_cl_movement_track_canjump;
+.float cvar_cl_movement_track_canjump = _STAT(MOVEVARS_CL_TRACK_CANJUMP);
 .float cvar_cl_newusekeysupported;
 
 .string cvar_g_xonoticversion;
@@ -254,7 +228,8 @@ void FixClientCvars(entity e);
 // WEAPONTODO: remove this
 WepSet weaponsInMap;
 
-.WepSet weaponsinmap;
+#define weapons _STAT(WEAPONS)
+#define weaponsinmap _STAT(WEAPONSINMAP)
 
 .float respawn_countdown; // next number to count
 
@@ -316,7 +291,7 @@ bool independent_players;
 
 string clientstuff;
 .float phase;
-.int pressedkeys;
+.int pressedkeys = _STAT(PRESSED_KEYS);
 
 .string fog;
 
@@ -327,7 +302,7 @@ float cvar_purechanges_count;
 float game_starttime; //point in time when the countdown to game start is over
 float round_starttime; //point in time when the countdown to round start is over
 .float stat_game_starttime = _STAT(GAMESTARTTIME);
-.float stat_round_starttime;
+.float stat_round_starttime = _STAT(ROUNDSTARTTIME);
 
 void W_Porto_Remove (entity p);
 
@@ -335,7 +310,7 @@ void W_Porto_Remove (entity p);
 
 .string message2;
 
-.float stat_allow_oldvortexbeam;
+.bool stat_allow_oldvortexbeam = _STAT(ALLOW_OLDVORTEXBEAM);
 
 // reset to 0 on weapon switch
 // may be useful to all weapons
@@ -372,18 +347,18 @@ float servertime, serverprevtime, serverframetime;
 .float floodcontrol_voice;
 .float floodcontrol_voiceteam;
 
-.float stat_shotorg; // networked stat for trueaim HUD
+.float stat_shotorg = _STAT(SHOTORG); // networked stat for trueaim HUD
 
 string matchid;
 
-.float last_pickup;
+.float last_pickup = _STAT(LAST_PICKUP);
 
-.float hit_time;
-.float typehit_time;
+.float hit_time = _STAT(HIT_TIME);
+.float typehit_time = _STAT(TYPEHIT_TIME);
 
-.float damage_dealt_total;
+.float damage_dealt_total = _STAT(DAMAGE_DEALT_TOTAL);
 
-.float stat_leadlimit;
+.float stat_leadlimit = _STAT(LEADLIMIT);
 
 bool radar_showennemies;
 
@@ -394,15 +369,15 @@ float client_cefc_accumulatortime;
 
 .float weapon_load[Weapons_MAX];
 .int ammo_none; // used by the reloading system, must always be 0
-.float clip_load;
+.float clip_load = _STAT(WEAPON_CLIPLOAD);
 .float old_clip_load;
-.float clip_size;
+.float clip_size = _STAT(WEAPON_CLIPSIZE);
 
-.float minelayer_mines;
-.float vortex_charge;
+.float minelayer_mines = _STAT(LAYED_MINES);
+.float vortex_charge = _STAT(VORTEX_CHARGE);
 .float vortex_charge_rottime;
-.float vortex_chargepool_ammo;
-.float hagar_load;
+.float vortex_chargepool_ammo = _STAT(VORTEX_CHARGEPOOL);
+.float hagar_load = _STAT(HAGAR_LOAD);
 
 .int grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
 
@@ -442,8 +417,8 @@ const float ACTIVE_TOGGLE   = 3;
 .float player_blocked;
 .float weapon_blocked; // weapon use disabled
 
-.float frozen; // for freeze attacks
-.float revive_progress;
+.float frozen = _STAT(FROZEN); // for freeze attacks
+.float revive_progress = _STAT(REVIVE_PROGRESS);
 .float revival_time; // time at which player was last revived
 .float revive_speed; // NOTE: multiplier (anything above 1 is instaheal)
 .entity iceblock;
@@ -452,7 +427,7 @@ const float ACTIVE_TOGGLE   = 3;
 .entity muzzle_flash;
 .float misc_bulletcounter;     // replaces uzi & hlac bullet counter.
 
-.float stat_respawn_time; // shows respawn time, and is negative when awaiting respawn
+.float stat_respawn_time = _STAT(RESPAWN_TIME); // shows respawn time, and is negative when awaiting respawn
 
 void PlayerUseKey();
 
index dc306eee097ee18631039db4d66ae5104ec74081..dfabd9d3dc9758b24fbbe9b0a843c581685bfe4c 100644 (file)
@@ -61,8 +61,8 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
        {
                // after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon
                Weapon culprit = DEATH_WEAPONOF(deathtype);
-               if(!culprit) culprit = get_weaponinfo(attacker.weapon);
-               else if(!(attacker.weapons & (culprit.m_wepset))) culprit = get_weaponinfo(attacker.weapon);
+               if(!culprit) culprit = Weapons_from(attacker.weapon);
+               else if(!(attacker.weapons & (culprit.m_wepset))) culprit = Weapons_from(attacker.weapon);
 
                if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator?
                {
@@ -95,7 +95,7 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
                }
 
                // after a frag, choose another random weapon set
-               if (!(attacker.weapons & WepSet_FromWeapon(attacker.weapon)))
+               if (!(attacker.weapons & WepSet_FromWeapon(Weapons_from(attacker.weapon))))
                        W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker));
        }
 
@@ -259,7 +259,7 @@ float Obituary_WeaponDeath(
        return false;
 }
 
-.int buffs; // TODO: remove
+.int buffs = _STAT(BUFFS); // TODO: remove
 
 void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
 {
index f2e3da898645ddfb755f0bd852e7a077988efa94..f7dcf3073a114b4dbf7078bc9e71cd7f0853c925 100644 (file)
@@ -11,50 +11,6 @@ spawnfunc(info_null)
        // if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
 }
 
-void setanim(entity e, vector anim, float looping, float override, float restart)
-{
-       if (!anim)
-               return; // no animation was given to us! We can't use this.
-
-       if (anim.x == e.animstate_startframe)
-       if (anim.y == e.animstate_numframes)
-       if (anim.z == e.animstate_framerate)
-       {
-               if(restart)
-               {
-                       if(restart > 0)
-                       if(anim.y == 1) // ZYM animation
-                               BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
-               }
-               else
-                       return;
-       }
-       e.animstate_startframe = anim.x;
-       e.animstate_numframes = anim.y;
-       e.animstate_framerate = anim.z;
-       e.animstate_starttime = servertime - 0.1 * serverframetime; // shift it a little bit into the past to prevent float inaccuracy hiccups
-       e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
-       e.animstate_looping = looping;
-       e.animstate_override = override;
-       e.frame = e.animstate_startframe;
-       e.frame1time = servertime;
-}
-
-void updateanim(entity e)
-{
-       if (time >= e.animstate_endtime)
-       {
-               if (e.animstate_looping)
-               {
-                       e.animstate_starttime = e.animstate_endtime;
-                       e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
-               }
-               e.animstate_override = false;
-       }
-       e.frame = e.animstate_startframe + bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1);
-       //print(ftos(time), " -> ", ftos(e.frame), "\n");
-}
-
 /*
 ==================
 main
index cebf61b7040d1b24302c4662e395272aadbd4a3f..81516f9357c56344f932fe70b439f282a6ddc72e 100644 (file)
@@ -9,12 +9,6 @@ void() SUB_CalcAngleMoveDone;
 
 spawnfunc(info_null);
 
-void setanim(entity e, vector anim, float looping, float override, float restart);
-
-void updateanim(entity e);
-
-
-
 /*
 ==================
 SUB_Friction
index 20abf4da390cbb07a32d74837e2be7f19e208d41..36b6074590031a955c67858c583585f7791a71d4 100644 (file)
@@ -561,7 +561,6 @@ void Nagger_Init();
 void ClientInit_Spawn();
 void WeaponStats_Init();
 void WeaponStats_Shutdown();
-void Physics_AddStats();
 spawnfunc(worldspawn)
 {
        float fd, l, j, n;
@@ -755,71 +754,8 @@ spawnfunc(worldspawn)
 
        WeaponStats_Init();
 
-       WepSet_AddStat();
-       WepSet_AddStat_InMap();
-       addstat(STAT_SWITCHINGWEAPON, AS_INT, switchingweapon);
-       addstat(STAT_ROUNDSTARTTIME, AS_FLOAT, stat_round_starttime);
-       addstat(STAT_ALLOW_OLDVORTEXBEAM, AS_INT, stat_allow_oldvortexbeam);
        Nagger_Init();
 
-       addstat(STAT_SUPERWEAPONS_FINISHED, AS_FLOAT, superweapons_finished);
-       addstat(STAT_PRESSED_KEYS, AS_FLOAT, pressedkeys);
-       addstat(STAT_FUEL, AS_INT, ammo_fuel);
-       addstat(STAT_PLASMA, AS_INT, ammo_plasma);
-       addstat(STAT_SHOTORG, AS_INT, stat_shotorg);
-       addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit);
-       addstat(STAT_WEAPON_CLIPLOAD, AS_INT, clip_load);
-       addstat(STAT_WEAPON_CLIPSIZE, AS_INT, clip_size);
-       addstat(STAT_LAST_PICKUP, AS_FLOAT, last_pickup);
-       addstat(STAT_HIT_TIME, AS_FLOAT, hit_time);
-       addstat(STAT_DAMAGE_DEALT_TOTAL, AS_INT, damage_dealt_total);
-       addstat(STAT_TYPEHIT_TIME, AS_FLOAT, typehit_time);
-       addstat(STAT_LAYED_MINES, AS_INT, minelayer_mines);
-
-       addstat(STAT_VORTEX_CHARGE, AS_FLOAT, vortex_charge);
-       addstat(STAT_VORTEX_CHARGEPOOL, AS_FLOAT, vortex_chargepool_ammo);
-
-       addstat(STAT_HAGAR_LOAD, AS_INT, hagar_load);
-
-       // freeze attacks
-       addstat(STAT_FROZEN, AS_INT, frozen);
-       addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, revive_progress);
-
-       // physics
-       Physics_AddStats();
-
-       // new properties
-       addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
-       addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
-       addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
-       addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
-       addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
-       addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
-       addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
-       addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
-       addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
-       addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
-       addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
-       addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
-       addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
-       addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
-
-       // secrets
-       addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
-       addstat(STAT_SECRETS_FOUND, AS_FLOAT, stat_secrets_found);
-
-       // monsters
-       addstat(STAT_MONSTERS_TOTAL, AS_FLOAT, stat_monsters_total);
-       addstat(STAT_MONSTERS_KILLED, AS_FLOAT, stat_monsters_killed);
-
-       // misc
-       addstat(STAT_RESPAWN_TIME, AS_FLOAT, stat_respawn_time);
-
        next_pingtime = time + 5;
 
        detect_maptype();
@@ -1473,18 +1409,21 @@ void FixIntermissionClient(entity e)
                        if(e.(weaponentity))
                        {
                                e.(weaponentity).effects = EF_NODRAW;
-                               if (e.(weaponentity).(weaponentity))
-                                       e.(weaponentity).(weaponentity).effects = EF_NODRAW;
+                               if (e.(weaponentity).weaponchild)
+                                       e.(weaponentity).weaponchild.effects = EF_NODRAW;
                        }
                }
                if(IS_REAL_CLIENT(e))
                {
                        stuffcmd(e, "\nscr_printspeed 1000000\n");
-                       string list = autocvar_sv_intermission_cdtrack;
-                       for(string it; (it = car(list)); list = cdr(list))
-                               RandomSelection_Add(world, 0, it, 1, 1);
-                       if(RandomSelection_chosen_string && RandomSelection_chosen_string != "")
-                               stuffcmd(e, strcat("\ncd loop ", RandomSelection_chosen_string, "\n"));
+                       RandomSelection_Init();
+                       FOREACH_WORD(autocvar_sv_intermission_cdtrack, true, LAMBDA(
+                               RandomSelection_Add(NULL, 0, it, 1, 1);
+                       ));
+                       if (RandomSelection_chosen_string != "")
+                       {
+                               stuffcmd(e, sprintf("\ncd loop %s\n", RandomSelection_chosen_string));
+                       }
                        msg_entity = e;
                        WriteByte(MSG_ONE, SVC_INTERMISSION);
                }
index ddf10818fe520e05b9aade437b41170e3d171781..e7eed32b43c5931998ca8425ab7a784f542b350c 100644 (file)
@@ -526,7 +526,7 @@ void readplayerstartcvars()
                g_weaponarena_list = "All Weapons";
                for (j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       e = get_weaponinfo(j);
+                       e = Weapons_from(j);
                        if (!(e.spawnflags & WEP_FLAG_MUTATORBLOCKED))
                                g_weaponarena_weapons |= (e.m_wepset);
                }
@@ -537,7 +537,7 @@ void readplayerstartcvars()
                g_weaponarena_list = "Most Weapons";
                for (j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       e = get_weaponinfo(j);
+                       e = Weapons_from(j);
                        if (!(e.spawnflags & WEP_FLAG_MUTATORBLOCKED))
                                if (e.spawnflags & WEP_FLAG_NORMAL)
                                        g_weaponarena_weapons |= (e.m_wepset);
@@ -558,7 +558,7 @@ void readplayerstartcvars()
                        s = argv(i);
                        for (j = WEP_FIRST; j <= WEP_LAST; ++j)
                        {
-                               e = get_weaponinfo(j);
+                               e = Weapons_from(j);
                                if (e.netname == s)
                                {
                                        g_weaponarena_weapons |= (e.m_wepset);
@@ -590,7 +590,7 @@ void readplayerstartcvars()
        {
                for (i = WEP_FIRST; i <= WEP_LAST; ++i)
                {
-                       e = get_weaponinfo(i);
+                       e = Weapons_from(i);
                        int w = want_weapon(e, false);
                        WepSet s = e.m_wepset;
                        if(w & 1)
@@ -653,7 +653,7 @@ void readplayerstartcvars()
                        warmup_start_weapons_defaultmask = '0 0 0';
                        for (i = WEP_FIRST; i <= WEP_LAST; ++i)
                        {
-                               e = get_weaponinfo(i);
+                               e = Weapons_from(i);
                                int w = want_weapon(e, g_warmup_allguns);
                                WepSet s = (e.m_wepset);
                                if(w & 1)
@@ -683,7 +683,7 @@ void readplayerstartcvars()
                precache_weapons |= warmup_start_weapons;
        for (i = WEP_FIRST; i <= WEP_LAST; ++i)
        {
-               e = get_weaponinfo(i);
+               e = Weapons_from(i);
                if(precache_weapons & (e.m_wepset)) {
                        e.wr_init(e);
                }
index 0976e60e581c4751a8701bf293529ca57faad2ec..8198338674923266b1e25261dedf21808e3428fb 100644 (file)
@@ -340,7 +340,7 @@ void readlevelcvars()
                game_starttime = time + cvar("g_start_delay");
 
        for(int i = WEP_FIRST; i <= WEP_LAST; ++i) {
-               Weapon w = get_weaponinfo(i);
+               Weapon w = Weapons_from(i);
                w.wr_init(w);
        }
 
index be95bd1a49a3d5e35660ffe1e1b14ab96a086ecb..75c1872aa2ccc510330e79772964835b80a7e911 100644 (file)
@@ -73,16 +73,6 @@ string weapon_sound;
 string weapon_sound_output;
 MUTATOR_HOOKABLE(WeaponSound, EV_WeaponSound);
 
-/** called when a weapon model is about to be set, allows custom paths etc. */
-#define EV_WeaponModel(i, o) \
-    /**/ i(string, weapon_model) \
-    /**/ i(string, weapon_model_output) \
-    /**/ o(string, weapon_model_output) \
-    /**/
-string weapon_model;
-string weapon_model_output;
-MUTATOR_HOOKABLE(WeaponModel, EV_WeaponModel);
-
 /** called when an item model is about to be set, allows custom paths etc. */
 #define EV_ItemModel(i, o) \
     /**/ i(string, item_model) \
@@ -838,4 +828,14 @@ MUTATOR_HOOKABLE(PrepareExplosionByDamage, EV_PrepareExplosionByDamage);
 string monster_model;
 string monster_model_output;
 MUTATOR_HOOKABLE(MonsterModel, EV_MonsterModel);
+
+/**/
+#define EV_Player_ChangeTeam(i, o) \
+    /**/ i(entity, __self) \
+    /**/ i(float, pct_curteam) \
+    /**/ i(float, pct_newteam) \
+    /**/
+float pct_curteam;
+float pct_newteam;
+MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam);
 #endif
index 5e2c4635734d27cdd3717ccfe1d76b4df39e37d5..06108be95f3b6d74f94a4de16c7a9bc285a45ac9 100644 (file)
@@ -40,6 +40,9 @@
 .float lastground;
 float total_players;
 float redalive, bluealive, yellowalive, pinkalive;
-.float redalive_stat, bluealive_stat, yellowalive_stat, pinkalive_stat;
+.float redalive_stat = _STAT(REDALIVE);
+.float bluealive_stat = _STAT(BLUEALIVE);
+.float yellowalive_stat = _STAT(YELLOWALIVE);
+.float pinkalive_stat = _STAT(PINKALIVE);
 
 #endif
index 9b9c8a05b6cedaca9daa36d8fb16d23f14224ce6..d4ca5cb3cc26ed4463de2ff1cef39b95c92a7fc9 100644 (file)
@@ -518,11 +518,6 @@ void ca_Initialize()
        round_handler_Spawn(CA_CheckTeams, CA_CheckWinner, CA_RoundStart);
        round_handler_Init(5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit);
 
-       addstat(STAT_REDALIVE, AS_INT, redalive_stat);
-       addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
-       addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat);
-       addstat(STAT_PINKALIVE, AS_INT, pinkalive_stat);
-
        EliminatedPlayers_Init(ca_isEliminated);
 }
 
index 086ab0cc22e7101b8b52532e38ac8613e1040704..432c32de710dead3ac8d9c185c2f05aa3a0c50c3 100644 (file)
@@ -183,7 +183,7 @@ void havocbot_role_ctf_setrole(entity bot, int role);
 #define CTF_DIFFTEAM(a,b) ((autocvar_g_ctf_reverse || (ctf_oneflag && autocvar_g_ctf_oneflag_reverse)) ? SAME_TEAM(a,b) : DIFF_TEAM(a,b))
 
 // networked flag statuses
-.int ctf_flagstatus;
+.int ctf_flagstatus = _STAT(CTF_FLAGSTATUS);
 #endif
 
 const int CTF_RED_FLAG_TAKEN                   = 1;
@@ -2759,7 +2759,7 @@ void ctf_DelayedInit() // Do this check with a delay so we can wait for teams to
        // if no teams are found, spawn defaults
        if(find(world, classname, "ctf_team") == world)
        {
-               LOG_INFO("No ""ctf_team"" entities found on this map, creating them anyway.\n");
+               LOG_INFO("No \"ctf_team\" entities found on this map, creating them anyway.\n");
                ctf_SpawnTeam("Red", NUM_TEAM_1 - 1);
                ctf_SpawnTeam("Blue", NUM_TEAM_2 - 1);
                if(ctf_teams >= 3)
@@ -2779,8 +2779,6 @@ void ctf_Initialize()
        ctf_captureshield_max_ratio = autocvar_g_ctf_shield_max_ratio;
        ctf_captureshield_force = autocvar_g_ctf_shield_force;
 
-       addstat(STAT_CTF_FLAGSTATUS, AS_INT, ctf_flagstatus);
-
        InitializeEntity(world, ctf_DelayedInit, INITPRIO_GAMETYPE);
 }
 
index 6d756fc679b615c74b878927f51838d1ab9aa72b..5e509a9daa10164088643b869edd2ab4951d7fd9 100644 (file)
@@ -11,11 +11,12 @@ REGISTER_MUTATOR(cts, false)
        {
                if (time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
-               cts_Initialize();
 
                g_race_qualifying = true;
                independent_players = 1;
-               SetLimits(0, 0, 0, -1);
+               SetLimits(0, 0, -1, -1);
+
+               cts_Initialize();
        }
 
        MUTATOR_ONROLLBACK_OR_REMOVE
@@ -216,16 +217,6 @@ MUTATOR_HOOKFUNCTION(cts, reset_map_global)
        return false;
 }
 
-MUTATOR_HOOKFUNCTION(cts, PlayerPreThink)
-{SELFPARAM();
-       if(IS_SPEC(self) || IS_OBSERVER(self))
-       if(g_race_qualifying)
-       if(msg_entity.enemy.race_laptime)
-               race_SendNextCheckpoint(msg_entity.enemy, 1);
-
-       return false;
-}
-
 MUTATOR_HOOKFUNCTION(cts, ClientConnect)
 {SELFPARAM();
        race_PreparePlayer();
index 9be5e108aa895be8d962c623c78dc4dd018611c2..da839e5171c3810418a44de41ff6211bd785338b 100644 (file)
@@ -42,11 +42,11 @@ const float ST_DOM_CAPS = 1;
 const float SP_DOM_CAPS = 4;
 
 // pps: points per second
-.float dom_total_pps;
-.float dom_pps_red;
-.float dom_pps_blue;
-.float dom_pps_yellow;
-.float dom_pps_pink;
+.float dom_total_pps = _STAT(DOM_TOTAL_PPS);
+.float dom_pps_red = _STAT(DOM_PPS_RED);
+.float dom_pps_blue = _STAT(DOM_PPS_BLUE);
+.float dom_pps_yellow = _STAT(DOM_PPS_YELLOW);
+.float dom_pps_pink = _STAT(DOM_PPS_PINK);
 float total_pps;
 float pps_red;
 float pps_blue;
@@ -695,7 +695,7 @@ void dom_DelayedInit() // Do this check with a delay so we can wait for teams to
        // if no teams are found, spawn defaults
        if(find(world, classname, "dom_team") == world || autocvar_g_domination_teams_override >= 2)
        {
-               LOG_INFO("No ""dom_team"" entities found on this map, creating them anyway.\n");
+               LOG_INFO("No \"dom_team\" entities found on this map, creating them anyway.\n");
                domination_teams = bound(2, ((autocvar_g_domination_teams_override < 2) ? autocvar_g_domination_default_teams : autocvar_g_domination_teams_override), 4);
                dom_spawnteams(domination_teams);
        }
@@ -703,12 +703,6 @@ void dom_DelayedInit() // Do this check with a delay so we can wait for teams to
        CheckAllowedTeams(world);
        domination_teams = ((c4>=0) ? 4 : (c3>=0) ? 3 : 2);
 
-       addstat(STAT_DOM_TOTAL_PPS, AS_FLOAT, dom_total_pps);
-       addstat(STAT_DOM_PPS_RED, AS_FLOAT, dom_pps_red);
-       addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue);
-       if(domination_teams >= 3) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow);
-       if(domination_teams >= 4) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink);
-
        domination_roundbased = autocvar_g_domination_roundbased;
 
        ScoreRules_dom(domination_teams);
index 29ae0066848980f495ffb70b8a2bbce775230e5b..ad52c13e4c7bb1e2b93f6659ad8cc87f12fd7b29 100644 (file)
@@ -647,11 +647,6 @@ void freezetag_Initialize()
        round_handler_Spawn(freezetag_CheckTeams, freezetag_CheckWinner, func_null);
        round_handler_Init(5, autocvar_g_freezetag_warmup, autocvar_g_freezetag_round_timelimit);
 
-       addstat(STAT_REDALIVE, AS_INT, redalive_stat);
-       addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
-       addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat);
-       addstat(STAT_PINKALIVE, AS_INT, pinkalive_stat);
-
        EliminatedPlayers_Init(freezetag_isEliminated);
 }
 
index 5b67888485d450dd4a8bdde5f5495cd746188f52..124bc653a769053f775ef0ed059c9173dd54431c 100644 (file)
@@ -10,9 +10,9 @@ REGISTER_MUTATOR(rc, false)
        {
                if (time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
-               race_Initialize();
 
                rc_SetLimits();
+               race_Initialize();
        }
 
        MUTATOR_ONROLLBACK_OR_REMOVE
@@ -253,16 +253,6 @@ MUTATOR_HOOKFUNCTION(rc, reset_map_global)
        return false;
 }
 
-MUTATOR_HOOKFUNCTION(rc, PlayerPreThink)
-{SELFPARAM();
-       if(IS_SPEC(self) || IS_OBSERVER(self))
-       if(g_race_qualifying)
-       if(msg_entity.enemy.race_laptime)
-               race_SendNextCheckpoint(msg_entity.enemy, 1);
-
-       return false;
-}
-
 MUTATOR_HOOKFUNCTION(rc, ClientConnect)
 {SELFPARAM();
        race_PreparePlayer();
index 42415a495e7140dbab08c4e9a47c925f51be4022..5da71b8177bd303715397d6d73a0f9a614487b4e 100644 (file)
@@ -71,7 +71,7 @@ void tdm_DelayedInit()
        // if no teams are found, spawn defaults
        if(find(world, classname, "tdm_team") == world)
        {
-               LOG_INFO("No ""tdm_team"" entities found on this map, creating them anyway.\n");
+               LOG_INFO("No \"tdm_team\" entities found on this map, creating them anyway.\n");
 
                int numteams = min(4, autocvar_g_tdm_teams_override);
 
index f3e03424b18eb4f5f4e7c2eb2b7228aea92784da..5ca2c1ca99d4450c11ad86b526f23cfaa869ec74 100644 (file)
@@ -146,9 +146,9 @@ float playerdemo_read(entity this)
                PLAYERDEMO_FIELDS(playerdemo_read_)
                {
                        time = this.playerdemo_time;
-                       WITH(entity, this, this, PlayerPreThink());
+                       WITH(entity, self, this, PlayerPreThink());
                        // not running physics though... this is just so we can run weapon stuff
-                       WITH(entity, this, this, PlayerPostThink());
+                       WITH(entity, self, this, PlayerPostThink());
                }
                this.playerdemo_time = stof(fgets(this.playerdemo_fh));
                if(this.playerdemo_time == 0)
index e23909812d27dd6494ace3e26b6a9aa42ce49d7a..5c79a0d88429e478effa0bbd766e66b83e2d5d6a 100644 (file)
@@ -53,6 +53,7 @@
 #include "weapons/weaponstats.qc"
 #include "weapons/weaponsystem.qc"
 
+#include "../common/anim.qc"
 #include "../common/animdecide.qc"
 #include "../common/campaign_file.qc"
 #include "../common/campaign_setup.qc"
index 093946d97e7fbb7ec96d709231925a5d41ccc5a4..304022f8e9ef60794b1729df2b2debecef6287d9 100644 (file)
 #include "../lib/warpzone/common.qh"
 #include "../common/mutators/mutator/waypoints/waypointsprites.qh"
 
+void race_InitSpectator()
+{
+       if(g_race_qualifying)
+               if(msg_entity.enemy.race_laptime)
+                       race_SendNextCheckpoint(msg_entity.enemy, 1);
+}
+
 void W_Porto_Fail(float failhard);
 
 float race_readTime(string map, float pos)
index 03e8a54aba2747e2f04f6f0914d7e23a2717fccb..c78c7765bb40a4d5f81a1aeed5212ec8bbe0217a 100644 (file)
@@ -57,4 +57,6 @@ void race_SendRankings(float pos, float prevpos, float del, float msg);
 
 void race_RetractPlayer();
 
+void race_InitSpectator();
+
 #endif
index 2eca07bc94843d8e8a9c75bebe3067e9e2febe62..03f3dbba37208d2eed5c5c8cc26fd18e628d3f49 100644 (file)
@@ -533,21 +533,20 @@ void WinningConditionHelper()
                if(fullstatus)
                {
                        s = GetPlayerScoreString(p, 1);
-                       if(IS_REAL_CLIENT(p))
-                               s = strcat(s, ":human");
-                       else
-                               s = strcat(s, ":bot");
+                       s = strcat(s, IS_REAL_CLIENT(p) ? ":human" : ":bot");
+                       ret_string = string_null;
                        if(!IS_PLAYER(p) && !MUTATOR_CALLHOOK(GetPlayerStatus, p, s))
                                s = strcat(s, ":spectator");
-                       s = strcat(s, ret_string);
+                       if (ret_string) s = strcat(s, ret_string);
                }
                else
                {
-                       if(IS_PLAYER(p) || MUTATOR_CALLHOOK(GetPlayerStatus, p, s))
+                       ret_string = string_null;
+                       if (IS_PLAYER(p) || MUTATOR_CALLHOOK(GetPlayerStatus, p, s))
                                s = GetPlayerScoreString(p, 2);
                        else
                                s = "-666";
-                       s = strcat(s, ret_string);
+                       if (ret_string) s = strcat(s, ret_string);
                }
 
                if(p.clientstatus)
index b970bdb2291e7e6020e3420cd0f13e324ee4eff7..90e9f79384cd3dfc4eaaf8fdddb6fedf4d4b3fe4 100644 (file)
 .float lastground;
 .int state;
 
-void CreatureFrame ()
-{SELFPARAM();
-       float dm;
-
-       for(entity e = world; (e = findfloat(e, damagedbycontents, true)); )
+void CreatureFrame_hotliquids(entity this)
+{
+       if (this.dmgtime < time)
        {
-               setself(e);
-               if (self.movetype == MOVETYPE_NOCLIP) { continue; }
-
-               float vehic = IS_VEHICLE(self);
-               float projectile = (self.flags & FL_PROJECTILE);
-               float monster = IS_MONSTER(self);
+               this.dmgtime = time + autocvar_g_balance_contents_damagerate;
 
-               if (self.watertype <= CONTENT_WATER && self.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
+               if (this.flags & FL_PROJECTILE)
                {
-                       if (!(self.flags & FL_INWATER))
-                       {
-                               self.flags |= FL_INWATER;
-                               self.dmgtime = 0;
-                       }
-
-                       if(!vehic && !projectile && !monster) // vehicles, monsters and projectiles don't drown
+                       if (this.watertype == CONTENT_LAVA)
+                               Damage (this, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, this.origin, '0 0 0');
+                       else if (this.watertype == CONTENT_SLIME)
+                               Damage (this, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, this.origin, '0 0 0');
+               }
+               else
+               {
+                       if (this.watertype == CONTENT_LAVA)
                        {
-                               if (self.waterlevel != WATERLEVEL_SUBMERGED)
+                               if (this.watersound_finished < time)
                                {
-                                       if(self.air_finished < time)
-                                               PlayerSound(playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                                       self.air_finished = time + autocvar_g_balance_contents_drowndelay;
-                                       self.dmg = 2;
-                               }
-                               else if (self.air_finished < time)
-                               {       // drown!
-                                       if (!self.deadflag)
-                                       if (self.pain_finished < time)
-                                       {
-                                               Damage (self, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, self.origin, '0 0 0');
-                                               self.pain_finished = time + 0.5;
-                                       }
+                                       this.watersound_finished = time + 0.5;
+                                       sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
                                }
+                               Damage (this, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, this.origin, '0 0 0');
+                               if(autocvar_g_balance_contents_playerdamage_lava_burn)
+                                       Fire_AddDamage(this, world, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
                        }
-
-                       if (self.dmgtime < time)
+                       else if (this.watertype == CONTENT_SLIME)
                        {
-                               self.dmgtime = time + autocvar_g_balance_contents_damagerate;
-
-                               if (projectile)
-                               {
-                                       if (self.watertype == CONTENT_LAVA)
-                                       {
-                                               Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA.m_id, self.origin, '0 0 0');
-                                       }
-                                       else if (self.watertype == CONTENT_SLIME)
-                                       {
-                                               Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME.m_id, self.origin, '0 0 0');
-                                       }
-                               }
-                               else
+                               if (this.watersound_finished < time)
                                {
-                                       if (self.watertype == CONTENT_LAVA)
-                                       {
-                                               if (self.watersound_finished < time)
-                                               {
-                                                       self.watersound_finished = time + 0.5;
-                                                       sound (self, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
-                                               }
-                                               Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA.m_id, self.origin, '0 0 0');
-                                               if(autocvar_g_balance_contents_playerdamage_lava_burn)
-                                                       Fire_AddDamage(self, world, autocvar_g_balance_contents_playerdamage_lava_burn * self.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * self.waterlevel, DEATH_LAVA.m_id);
-                                       }
-                                       else if (self.watertype == CONTENT_SLIME)
-                                       {
-                                               if (self.watersound_finished < time)
-                                               {
-                                                       self.watersound_finished = time + 0.5;
-                                                       sound (self, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
-                                               }
-                                               Damage (self, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME.m_id, self.origin, '0 0 0');
-                                       }
+                                       this.watersound_finished = time + 0.5;
+                                       sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
                                }
+                               Damage (this, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, this.origin, '0 0 0');
                        }
                }
-               else
+       }
+}
+
+void CreatureFrame_Liquids(entity this)
+{
+       if (this.watertype <= CONTENT_WATER && this.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
+       {
+               if (!(this.flags & FL_INWATER))
                {
-                       if (self.flags & FL_INWATER)
-                       {
-                               // play leave water sound
-                               self.flags &= ~FL_INWATER;
-                               self.dmgtime = 0;
-                       }
-                       self.air_finished = time + 12;
-                       self.dmg = 2;
+                       this.flags |= FL_INWATER;
+                       this.dmgtime = 0;
                }
 
-               if(!vehic && !projectile) // vehicles don't get falling damage
+               CreatureFrame_hotliquids(this);
+       }
+       else
+       {
+               if (this.flags & FL_INWATER)
                {
-                       // check for falling damage
-                       float velocity_len = vlen(self.velocity);
-                       if(!self.hook.state)
-                       {
-                               dm = vlen(self.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
-                               if (self.deadflag)
-                                       dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
-                               else
-                                       dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
-                               if (dm > 0)
-                                       Damage (self, world, world, dm, DEATH_FALL.m_id, self.origin, '0 0 0');
-                       }
+                       // play leave water sound
+                       this.flags &= ~FL_INWATER;
+                       this.dmgtime = 0;
+               }
+               this.air_finished = time + 12;
+               this.dmg = 2;
+       }
+}
 
-                       if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
-                               Damage (self, world, world, 100000, DEATH_SHOOTING_STAR.m_id, self.origin, '0 0 0');
-                       // play stupid sounds
-                       if (g_footsteps)
-                       if (!gameover)
-                       if (self.flags & FL_ONGROUND)
-                       if (!self.crouch)
-                       if (velocity_len > autocvar_sv_maxspeed * 0.6)
-                       if (!self.deadflag)
-                       if (time < self.lastground + 0.2)
-                       {
-                               if((time > self.nextstep) || (time < (self.nextstep - 10.0)))
-                               {
-                                       self.nextstep = time + 0.3 + random() * 0.1;
-                                       trace_dphitq3surfaceflags = 0;
-                                       tracebox(self.origin, self.mins, self.maxs, self.origin - '0 0 1', MOVE_NOMONSTERS, self);
-                                       /*
-                                       if(trace_fraction == 1)
-                                               dprint("nohit\n");
-                                       else
-                                               dprint(ftos(trace_dphitq3surfaceflags), "\n");
-                                       */
-                                       if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS))
-                                       {
-                                               if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
-                                                       GlobalSound(GS_STEP_METAL, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                                               else
-                                                       GlobalSound(GS_STEP, CH_PLAYER, VOICETYPE_PLAYERSOUND);
-                                       }
-                               }
-                       }
+void CreatureFrame_FallDamage(entity this)
+{
+       if(!IS_VEHICLE(this) && !(this.flags & FL_PROJECTILE)) // vehicles don't get falling damage
+       {
+               // check for falling damage
+               float velocity_len = vlen(this.velocity);
+               if(!this.hook.state)
+               {
+                       float dm = vlen(this.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
+                       if (this.deadflag)
+                               dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
+                       else
+                               dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
+                       if (dm > 0)
+                               Damage (this, world, world, dm, DEATH_FALL.m_id, this.origin, '0 0 0');
                }
 
-        self.oldvelocity = self.velocity;
+               if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
+                       Damage (this, world, world, 100000, DEATH_SHOOTING_STAR.m_id, this.origin, '0 0 0');
+       }
+}
+
+void CreatureFrame_All()
+{
+       for(entity e = world; (e = findfloat(e, damagedbycontents, true)); )
+       {
+               if (e.movetype == MOVETYPE_NOCLIP) { continue; }
+
+               CreatureFrame_Liquids(e);
+               CreatureFrame_FallDamage(e);
+
+        e.oldvelocity = e.velocity;
        }
-       setself(this);
 }
 
 
@@ -248,7 +201,7 @@ void StartFrame()
 
        game_delay_last = game_delay;
 
-       CreatureFrame();
+       CreatureFrame_All();
        CheckRules_World();
 
        // if in warmup stage and limit for warmup is hit start match
@@ -264,6 +217,13 @@ void StartFrame()
        bot_serverframe();
        anticheat_startframe();
        MUTATOR_CALLHOOK(SV_StartFrame);
+       {
+        entity e;
+        FOR_EACH_CLIENT(e)
+        {
+            GlobalStats_update(e);
+        }
+    }
 }
 
 .vector originjitter;
index 3fb6998e9ce43fd3d1640e2376bf93410591a976..97f63fc298db513777a5c84201a3e0738ede88b6 100644 (file)
@@ -491,7 +491,7 @@ void Item_RespawnCountdown ()
                        MUTATOR_CALLHOOK(Item_RespawnCountdown, string_null, '0 0 0');
                        do {
                                {
-                                       entity wi = get_weaponinfo(self.weapon);
+                                       entity wi = Weapons_from(self.weapon);
                                        if (wi.m_id) {
                                                entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Weapon);
                                                wp.wp_extra = wi.m_id;
@@ -645,7 +645,7 @@ float Item_GiveTo(entity item, entity player)
        if (player.switchweapon == w_getbestweapon(player))
                _switchweapon = true;
 
-       if (!(player.weapons & WepSet_FromWeapon(player.switchweapon)))
+       if (!(player.weapons & WepSet_FromWeapon(Weapons_from(player.switchweapon))))
                _switchweapon = true;
 
        pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
@@ -667,7 +667,7 @@ float Item_GiveTo(entity item, entity player)
                {
                        pickedup = true;
                        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-                       if(it & WepSet_FromWeapon(i))
+                       if(it & WepSet_FromWeapon(Weapons_from(i)))
                        {
                                W_DropEvent(wr_pickup, player, i, item);
                                W_GiveWeapon(player, i);
@@ -929,7 +929,7 @@ float commodity_pickupevalfunc(entity player, entity item)
        // Detect needed ammo
        for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
        {
-               wi = get_weaponinfo(i);
+               wi = Weapons_from(i);
 
                if (!(player.weapons & (wi.m_wepset)))
                        continue;
@@ -1023,7 +1023,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
        }
 
        if(weaponid)
-               this.weapons = WepSet_FromWeapon(weaponid);
+               this.weapons = WepSet_FromWeapon(Weapons_from(weaponid));
 
        this.flags = FL_ITEM | itemflags;
 
@@ -1126,7 +1126,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                        this.is_item = true;
                }
 
-               weaponsInMap |= WepSet_FromWeapon(weaponid);
+               weaponsInMap |= WepSet_FromWeapon(Weapons_from(weaponid));
 
                precache_model(this.model);
                precache_sound(this.item_pickupsound);
@@ -1442,13 +1442,13 @@ spawnfunc(target_items)
                        {
                                for(j = WEP_FIRST; j <= WEP_LAST; ++j)
                                {
-                                       e = get_weaponinfo(j);
+                                       e = Weapons_from(j);
                                        s = W_UndeprecateName(argv(i));
                                        if(s == e.netname)
                                        {
                                                self.weapons |= (e.m_wepset);
                                                if(self.spawnflags == 0 || self.spawnflags == 2) {
-                                                       Weapon w = get_weaponinfo(e.weapon);
+                                                       Weapon w = Weapons_from(e.weapon);
                                                        w.wr_init(w);
                                                }
                                                break;
@@ -1504,7 +1504,7 @@ spawnfunc(target_items)
                if(self.armorvalue != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.health), "armor");
                for(j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       e = get_weaponinfo(j);
+                       e = Weapons_from(j);
                        if(e.weapon)
                                self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.weapons & (e.m_wepset)), e.netname);
                }
@@ -1517,10 +1517,10 @@ spawnfunc(target_items)
        {
                for(j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       e = get_weaponinfo(j);
+                       e = Weapons_from(j);
                        if(argv(i) == e.netname)
                        {
-                               Weapon w = get_weaponinfo(e.weapon);
+                               Weapon w = Weapons_from(e.weapon);
                                w.wr_init(w);
                                break;
                        }
@@ -1562,7 +1562,7 @@ spawnfunc(item_jetpack)
 float GiveWeapon(entity e, float wpn, float op, float val)
 {
        WepSet v0, v1;
-       WepSet s = WepSet_FromWeapon(wpn);
+       WepSet s = WepSet_FromWeapon(Weapons_from(wpn));
        v0 = (e.weapons & s);
        switch(op)
        {
@@ -1688,7 +1688,7 @@ float GiveItems(entity e, float beginarg, float endarg)
                        case "allweapons":
                                for(j = WEP_FIRST; j <= WEP_LAST; ++j)
                                {
-                                       wi = get_weaponinfo(j);
+                                       wi = Weapons_from(j);
                                        if(wi.weapon)
                                                if (!(wi.spawnflags & WEP_FLAG_MUTATORBLOCKED))
                                                        got += GiveWeapon(e, j, op, val);
@@ -1753,7 +1753,7 @@ float GiveItems(entity e, float beginarg, float endarg)
                        default:
                                for(j = WEP_FIRST; j <= WEP_LAST; ++j)
                                {
-                                       wi = get_weaponinfo(j);
+                                       wi = Weapons_from(j);
                                        if(cmd == wi.netname)
                                        {
                                                got += GiveWeapon(e, j, op, val);
@@ -1774,13 +1774,13 @@ float GiveItems(entity e, float beginarg, float endarg)
        POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, SND(ITEMPICKUP), string_null);
        for(j = WEP_FIRST; j <= WEP_LAST; ++j)
        {
-               wi = get_weaponinfo(j);
+               wi = Weapons_from(j);
                if(wi.weapon)
                {
-                       POSTGIVE_WEAPON(e, j, SND(WEAPONPICKUP), string_null);
+                       POSTGIVE_WEAPON(e, Weapons_from(j), SND(WEAPONPICKUP), string_null);
                        if (!(save_weapons & (wi.m_wepset)))
                                if(e.weapons & (wi.m_wepset)) {
-                                       Weapon w = get_weaponinfo(wi.weapon);
+                                       Weapon w = Weapons_from(wi.weapon);
                                        w.wr_init(w);
                                }
                }
@@ -1813,7 +1813,7 @@ float GiveItems(entity e, float beginarg, float endarg)
        else
                e.superweapons_finished += time;
 
-       if (!(e.weapons & WepSet_FromWeapon(e.switchweapon)))
+       if (!(e.weapons & WepSet_FromWeapon(Weapons_from(e.switchweapon))))
                _switchweapon = true;
        if(_switchweapon)
                W_SwitchWeapon_Force(e, w_getbestweapon(e));
index b0f44da6b7e51d5104d3d01b1571b3c149bc874c..0662aab68ece77f479b001efc99f4a11cee5c488 100644 (file)
@@ -651,6 +651,8 @@ void SV_ChangeTeam(float _color)
        if(!IS_CLIENT(self))
                Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_CONNECTING, self.netname);
 
+       MUTATOR_CALLHOOK(Player_ChangeTeam, self, steam, dteam);
+
        SetPlayerTeam(self, dteam, steam, !IS_CLIENT(self));
 
        if(IS_PLAYER(self) && steam != dteam)
index 211ef8cec090682aeaf040286f54018f8ff27376..b92a21da2d6352f63ba88b08884c21e7a39a0327 100644 (file)
@@ -58,7 +58,7 @@ void accuracy_resend(entity e)
 }
 
 // update accuracy stats
-.float hit_time;
+//.float hit_time;
 .float fired_time;
 
 void accuracy_add(entity this, int w, int fired, int hit)
index ef3d185c03e64f63ba6ab6474b66cb054bbc3789..b100259ef541987941cda6d4a1bdf4508097940b 100644 (file)
@@ -14,7 +14,7 @@ void W_GiveWeapon (entity e, float wep)
        if (!wep)
                return;
 
-       e.weapons |= WepSet_FromWeapon(wep);
+       e.weapons |= WepSet_FromWeapon(Weapons_from(wep));
 
        setself(e);
 
index 8efa15b3243ad38faaa14956dda8c9af0ecc64d4..b301da6f2e46ff7eb44cf0929fbce458b0537deb 100644 (file)
@@ -26,7 +26,7 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
 
        // ignore hook button when using other offhand equipment
        if (cl.offhand != OFFHAND_HOOK)
-       if (wpn == WEP_HOOK.m_id && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn)))
+       if (wpn == WEP_HOOK.m_id && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(Weapons_from(wpn))))
            complain = 0;
 
        if(complain)
@@ -38,7 +38,7 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                        sprint(self, "Invalid weapon\n");
                return false;
        }
-       if (cl.weapons & WepSet_FromWeapon(wpn))
+       if (cl.weapons & WepSet_FromWeapon(Weapons_from(wpn)))
        {
                if (andammo)
                {
@@ -49,7 +49,7 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                        else
                        {
                                setself(cl);
-                               Weapon w = get_weaponinfo(wpn);
+                               Weapon w = Weapons_from(wpn);
                                f = w.wr_checkammo1(w) + w.wr_checkammo2(w);
 
                                // always allow selecting the Mine Layer if we placed mines, so that we can detonate them
@@ -77,7 +77,7 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
        {
                // DRESK - 3/16/07
                // Report Proper Weapon Status / Modified Weapon Ownership Message
-               if (weaponsInMap & WepSet_FromWeapon(wpn))
+               if (weaponsInMap & WepSet_FromWeapon(Weapons_from(wpn)))
                {
                        Send_WeaponComplain(cl, wpn, 1);
 
@@ -139,7 +139,7 @@ float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, floa
        while(rest != "")
        {
                weaponwant = stof(car(rest)); rest = cdr(rest);
-               wep = get_weaponinfo(weaponwant);
+               wep = Weapons_from(weaponwant);
                wepset = wep.m_wepset;
                if(imp >= 0)
                if(wep.impulse != imp)
@@ -148,7 +148,7 @@ float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, floa
                float i, have_other = false;
                for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                {
-                       Weapon e = get_weaponinfo(i);
+                       Weapon e = Weapons_from(i);
                        if(i != weaponwant)
                        if(e.impulse == imp || imp < 0)
                        if((pl.weapons & (e.m_wepset)) || (weaponsInMap & (e.m_wepset)))
@@ -197,7 +197,7 @@ float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, floa
                while(rest != "")
                {
                        weaponwant = stof(car(rest)); rest = cdr(rest);
-                       wep = get_weaponinfo(weaponwant);
+                       wep = Weapons_from(weaponwant);
                        wepset = wep.m_wepset;
                        if(imp >= 0)
                                if(wep.impulse != imp)
@@ -206,7 +206,7 @@ float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, floa
                        float i, have_other = false;
                        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                        {
-                               Weapon w = get_weaponinfo(i);
+                               Weapon w = Weapons_from(i);
                                if(i != weaponwant)
                                if(w.impulse == imp || imp < 0)
                                if((pl.weapons & (w.m_wepset)) || (weaponsInMap & (w.m_wepset)))
@@ -242,7 +242,7 @@ void W_SwitchToOtherWeapon(entity pl)
 {
        // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
        int ww;
-       WepSet set = WepSet_FromWeapon(pl.weapon);
+       WepSet set = WepSet_FromWeapon(Weapons_from(pl.weapon));
        if(pl.weapons & set)
        {
                pl.weapons &= ~set;
@@ -265,7 +265,7 @@ void W_SwitchWeapon(float imp)
                        self.selectweapon = imp; // update selectweapon ANYWAY
        }
        else if(!forbidWeaponUse(self)) {
-               Weapon w = get_weaponinfo(self.weapon);
+               Weapon w = Weapons_from(self.weapon);
                w.wr_reload(w);
        }
 }
index 244f6a5e6d768bfcc8d47ce357836f45cf805bac..c362913d45aa3cc8f2039640b39d62c791204ba0 100644 (file)
@@ -18,7 +18,7 @@ string W_Apply_Weaponreplace(string in)
 
                for(j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       e = get_weaponinfo(j);
+                       e = Weapons_from(j);
                        if(e.netname == s)
                        {
                                replacement = e.weaponreplace;
@@ -64,7 +64,7 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                                int j;
                                for (j = WEP_FIRST; j <= WEP_LAST; ++j)
                                {
-                                       e = get_weaponinfo(j);
+                                       e = Weapons_from(j);
                                        if (e.netname == s)
                                        {
                                                entity replacement = spawn();
@@ -87,7 +87,7 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                        int j;
                        for (j = WEP_FIRST; j <= WEP_LAST; ++j)
                        {
-                               e = get_weaponinfo(j);
+                               e = Weapons_from(j);
                                if (e.netname == s)
                                {
                                        wpn = j;
@@ -107,11 +107,11 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                }
        }
 
-       e = get_weaponinfo(wpn);
+       e = Weapons_from(wpn);
 
        if (!this.respawntime)
        {
-               if (e.weapons & WEPSET_SUPERWEAPONS)
+               if (e.spawnflags & WEP_FLAG_SUPERWEAPON)
                {
                        this.respawntime = g_pickup_respawntime_superweapon;
                        this.respawntimejitter = g_pickup_respawntimejitter_superweapon;
@@ -123,9 +123,12 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                }
        }
 
-       if (e.weapons & WEPSET_SUPERWEAPONS)
+       if (e.spawnflags & WEP_FLAG_SUPERWEAPON)
                if (!this.superweapons_finished)
+               {
                        this.superweapons_finished = autocvar_g_balance_superweapons_time;
+                       LOG_INFO("Setting it to ", ftos(this.superweapons_finished), " on ", e.mdl, "\n");
+               }
 
        // if we don't already have ammo, give us some ammo
        if (!this.(e.ammo_field))
index 6f4546e01c4a26100076628aff9826da5461f0cd..652ec92005aba884ea26c3955b42644fb33a6726 100644 (file)
@@ -34,7 +34,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
 {SELFPARAM();
        float thisammo, i;
        string s;
-       Weapon info = get_weaponinfo(wpn);
+       Weapon info = Weapons_from(wpn);
        var .int ammotype = info.ammo_field;
 
        entity wep = new(droppedweapon);
@@ -47,7 +47,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
 
        W_DropEvent(wr_drop,own,wpn,wep);
 
-       if(WepSet_FromWeapon(wpn) & WEPSET_SUPERWEAPONS)
+       if(WepSet_FromWeapon(Weapons_from(wpn)) & WEPSET_SUPERWEAPONS)
        {
                if(own.items & IT_UNLIMITED_SUPERWEAPONS)
                {
@@ -58,7 +58,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                        float superweapons = 1;
                        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                        {
-                               WepSet set = WepSet_FromWeapon(i);
+                               WepSet set = WepSet_FromWeapon(Weapons_from(i));
                                if ((set & WEPSET_SUPERWEAPONS) && (own.weapons & set)) ++superweapons;
                        }
                        if(superweapons <= 1)
@@ -148,17 +148,17 @@ bool W_IsWeaponThrowable(bool w)
         return false;
 
        #if 0
-       if(start_weapons & WepSet_FromWeapon(w))
+       if(start_weapons & WepSet_FromWeapon(Weapons_from(w)))
        {
                // start weapons that take no ammo can't be dropped (this prevents dropping the laser, as long as it continues to use no ammo)
                if(start_items & IT_UNLIMITED_WEAPON_AMMO)
                        return false;
-               if((get_weaponinfo(w)).ammo_field == ammo_none)
+               if((Weapons_from(w)).ammo_field == ammo_none)
                        return false;
        }
        return true;
        #else
-       return (get_weaponinfo(w)).weaponthrowable;
+       return (Weapons_from(w)).weaponthrowable;
        #endif
 }
 
@@ -178,7 +178,7 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce)
        if(!W_IsWeaponThrowable(w))
                return;
 
-       WepSet set = WepSet_FromWeapon(w);
+       WepSet set = WepSet_FromWeapon(Weapons_from(w));
        if(!(self.weapons & set)) return;
        self.weapons &= ~set;
 
@@ -191,7 +191,7 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce)
 
 void SpawnThrownWeapon(vector org, float w)
 {SELFPARAM();
-       if(self.weapons & WepSet_FromWeapon(self.weapon))
+       if(self.weapons & WepSet_FromWeapon(Weapons_from(self.weapon)))
                if(W_IsWeaponThrowable(self.weapon))
                        W_ThrowNewWeapon(self, self.weapon, false, org, randomvec() * 125 + '0 0 200');
 }
index 3ea45ad46814ca7dfcc306288048b41cded229fb..7607ae18c57ce2a1a7f8386173abe3eb55ba1cb7 100644 (file)
 #include "../../common/weapons/all.qh"
 #include "../../lib/csqcmodel/sv_model.qh"
 
-vector shotorg_adjustfromclient(vector vecs, float y_is_right, float algn)
-{
-       switch (algn)
-       {
-               default: case 3: break; // right alignment
-               case 4: vecs.y = -vecs.y;
-                       break;              // left
-               case 1: case 2: vecs.y = 0;
-                       vecs.z -= 2;
-                       break;              // center
-       }
-
-       return vecs;
-}
-
-vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn)
-{
-       string s;
-
-       if (visual)
-       {
-               vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
-       }
-       else if (autocvar_g_shootfromeye)
-       {
-               vecs.y = vecs.z = 0;
-       }
-       else if (autocvar_g_shootfromcenter)
-       {
-               vecs.y = 0;
-               vecs.z -= 2;
-       }
-       else if ((s = autocvar_g_shootfromfixedorigin) != "")
-       {
-               vector v = stov(s);
-               if (y_is_right) v.y = -v.y;
-               if (v.x != 0) vecs.x = v.x;
-               vecs.y = v.y;
-               vecs.z = v.z;
-       }
-       else  // just do the same as top
-       {
-               vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
-       }
-
-       return vecs;
-}
-
-vector shotorg_adjust(vector vecs, bool y_is_right, bool visual, int algn)
-{
-       return shotorg_adjust_values(vecs, y_is_right, visual, algn);
-}
-
 .int state;
 
 .float weapon_frametime;
@@ -92,9 +39,6 @@ float W_WeaponSpeedFactor()
 }
 
 
-void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(Weapon thiswep, entity actor,
-    .entity weaponentity, int fire) func);
-
 bool CL_Weaponentity_CustomizeEntityForClient()
 {
        SELFPARAM();
@@ -103,224 +47,19 @@ bool CL_Weaponentity_CustomizeEntityForClient()
        return true;
 }
 
-/*
- * supported formats:
- *
- * 1. simple animated model, muzzle flash handling on h_ model:
- *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
- *      tags:
- *        shot = muzzle end (shot origin, also used for muzzle flashes)
- *        shell = casings ejection point (must be on the right hand side of the gun)
- *        weapon = attachment for v_tuba.md3
- *    v_tuba.md3 - first and third person model
- *    g_tuba.md3 - pickup model
- *
- * 2. simple animated model, muzzle flash handling on v_ model:
- *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
- *      tags:
- *        weapon = attachment for v_tuba.md3
- *    v_tuba.md3 - first and third person model
- *      tags:
- *        shot = muzzle end (shot origin, also used for muzzle flashes)
- *        shell = casings ejection point (must be on the right hand side of the gun)
- *    g_tuba.md3 - pickup model
- *
- * 3. fully animated model, muzzle flash handling on h_ model:
- *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
- *      tags:
- *        shot = muzzle end (shot origin, also used for muzzle flashes)
- *        shell = casings ejection point (must be on the right hand side of the gun)
- *        handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes)
- *    v_tuba.md3 - third person model
- *    g_tuba.md3 - pickup model
- *
- * 4. fully animated model, muzzle flash handling on v_ model:
- *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
- *      tags:
- *        shot = muzzle end (shot origin)
- *        shell = casings ejection point (must be on the right hand side of the gun)
- *    v_tuba.md3 - third person model
- *      tags:
- *        shot = muzzle end (for muzzle flashes)
- *    g_tuba.md3 - pickup model
- */
-
-// writes:
-//   this.origin, this.angles
-//   this.weaponentity
-//   this.movedir, this.view_ofs
-//   attachment stuff
-//   anim stuff
-// to free:
-//   call again with ""
-//   remove the ent
-void CL_WeaponEntity_SetModel(entity this, .entity weaponentity, string name)
-{
-       if (name != "")
-       {
-               // if there is a child entity, hide it until we're sure we use it
-               if (this.(weaponentity)) this.(weaponentity).model = "";
-               _setmodel(this, W_Model(strcat("v_", name, ".md3")));
-               int v_shot_idx = gettagindex(this, "shot");  // used later
-               if (!v_shot_idx) v_shot_idx = gettagindex(this, "tag_shot");
-
-               _setmodel(this, W_Model(strcat("h_", name, ".iqm")));
-               // preset some defaults that work great for renamed zym files (which don't need an animinfo)
-               this.anim_fire1  = animfixfps(this, '0 1 0.01', '0 0 0');
-               this.anim_fire2  = animfixfps(this, '1 1 0.01', '0 0 0');
-               this.anim_idle   = animfixfps(this, '2 1 0.01', '0 0 0');
-               this.anim_reload = animfixfps(this, '3 1 0.01', '0 0 0');
-
-               // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
-               // if we don't, this is a "real" animated model
-               if (gettagindex(this, "weapon"))
-               {
-                       if (!this.(weaponentity)) this.(weaponentity) = new(weaponentity);
-                       _setmodel(this.(weaponentity), W_Model(strcat("v_", name, ".md3")));
-                       setattachment(this.(weaponentity), this, "weapon");
-               }
-               else if (gettagindex(this, "tag_weapon"))
-               {
-                       if (!this.(weaponentity)) this.(weaponentity) = new(weaponentity);
-                       _setmodel(this.(weaponentity), W_Model(strcat("v_", name, ".md3")));
-                       setattachment(this.(weaponentity), this, "tag_weapon");
-               }
-               else
-               {
-                       if (this.(weaponentity)) remove(this.(weaponentity));
-                       this.(weaponentity) = NULL;
-               }
-
-               setorigin(this, '0 0 0');
-               this.angles = '0 0 0';
-               this.frame = 0;
-               this.viewmodelforclient = NULL;
-
-               float idx;
-
-               if (v_shot_idx)  // v_ model attached to invisible h_ model
-               {
-                       this.movedir = gettaginfo(this.(weaponentity), v_shot_idx);
-               }
-               else
-               {
-                       idx = gettagindex(this, "shot");
-                       if (!idx) idx = gettagindex(this, "tag_shot");
-                       if (idx)
-                       {
-                               this.movedir = gettaginfo(this, idx);
-                       }
-                       else
-                       {
-                               LOG_INFO("WARNING: weapon model ", this.model,
-                                       " does not support the 'shot' tag, will display shots TOTALLY wrong\n");
-                               this.movedir = '0 0 0';
-                       }
-               }
-
-               if (this.(weaponentity))  // v_ model attached to invisible h_ model
-               {
-                       idx = gettagindex(this.(weaponentity), "shell");
-                       if (!idx) idx = gettagindex(this.(weaponentity), "tag_shell");
-                       if (idx) this.spawnorigin = gettaginfo(this.(weaponentity), idx);
-               }
-               else
-               {
-                       idx = 0;
-               }
-               if (!idx)
-               {
-                       idx = gettagindex(this, "shell");
-                       if (!idx) idx = gettagindex(this, "tag_shell");
-                       if (idx)
-                       {
-                               this.spawnorigin = gettaginfo(this, idx);
-                       }
-                       else
-                       {
-                               LOG_INFO("WARNING: weapon model ", this.model,
-                                       " does not support the 'shell' tag, will display casings wrong\n");
-                               this.spawnorigin = this.movedir;
-                       }
-               }
-
-               if (v_shot_idx)
-               {
-                       this.oldorigin = '0 0 0';  // use regular attachment
-               }
-               else
-               {
-                       if (this.(weaponentity))
-                       {
-                               idx = gettagindex(this, "weapon");
-                               if (!idx) idx = gettagindex(this, "tag_weapon");
-                       }
-                       else
-                       {
-                               idx = gettagindex(this, "handle");
-                               if (!idx) idx = gettagindex(this, "tag_handle");
-                       }
-                       if (idx)
-                       {
-                               this.oldorigin = this.movedir - gettaginfo(this, idx);
-                       }
-                       else
-                       {
-                               LOG_INFO("WARNING: weapon model ", this.model,
-                                       " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n");
-                               this.oldorigin = '0 0 0';  // there is no way to recover from this
-                       }
-               }
-
-               this.viewmodelforclient = this.owner;
-       }
-       else
-       {
-               this.model = "";
-               if (this.(weaponentity)) remove(this.(weaponentity));
-               this.(weaponentity) = NULL;
-               this.movedir = '0 0 0';
-               this.spawnorigin = '0 0 0';
-               this.oldorigin = '0 0 0';
-               this.anim_fire1  = '0 1 0.01';
-               this.anim_fire2  = '0 1 0.01';
-               this.anim_idle   = '0 1 0.01';
-               this.anim_reload = '0 1 0.01';
-       }
-
-       this.view_ofs = '0 0 0';
-
-       if (this.movedir.x >= 0)
-       {
-               vector v0 = this.movedir;
-               this.movedir = shotorg_adjust(v0, false, false, this.owner.cvar_cl_gunalign);
-               this.view_ofs = shotorg_adjust(v0, false, true, this.owner.cvar_cl_gunalign) - v0;
-       }
-       this.owner.stat_shotorg = compressShotOrigin(this.movedir);
-       this.movedir = decompressShotOrigin(this.owner.stat_shotorg); // make them match perfectly
-
-       this.spawnorigin += this.view_ofs;                            // offset the casings origin by the same amount
-
-       // check if an instant weapon switch occurred
-       setorigin(this, this.view_ofs);
-       // reset animstate now
-       this.wframe = WFRAME_IDLE;
-       setanim(this, this.anim_idle, true, false, true);
-}
-
-vector CL_Weapon_GetShotOrg(float wpn)
+vector CL_Weapon_GetShotOrg(int wpn)
 {
        entity wi = Weapons_from(wpn);
        entity e = spawn();
-       .entity weaponentity = weaponentities[0];
-       CL_WeaponEntity_SetModel(e, weaponentity, wi.mdl);
+       CL_WeaponEntity_SetModel(e, wi.mdl);
        vector ret = e.movedir;
-       CL_WeaponEntity_SetModel(e, weaponentity, "");
+       CL_WeaponEntity_SetModel(e, "");
        remove(e);
        return ret;
 }
 
 ..entity weaponentity_fld;
+.float m_alpha;
 
 void CL_Weaponentity_Think()
 {
@@ -330,68 +69,40 @@ void CL_Weaponentity_Think()
        .entity weaponentity = this.weaponentity_fld;
        if (this.owner.(weaponentity) != this)
        {
-               if (this.(weaponentity)) remove(this.(weaponentity));
+               // owner has new gun; remove self
+               if (this.weaponchild) remove(this.weaponchild);
                remove(this);
                return;
        }
        if (this.owner.deadflag != DEAD_NO)
        {
+               // owner died; disappear
                this.model = "";
-               if (this.(weaponentity)) this.(weaponentity).model = "";
+               if (this.weaponchild) this.weaponchild.model = "";
                return;
        }
-       if (this.weaponname != this.owner.weaponname || this.dmg != this.owner.modelindex
+       if (this.weaponname != this.owner.weaponname
+           || this.dmg != this.owner.modelindex
            || this.deadflag != this.owner.deadflag)
        {
+               // owner changed weapons; update appearance
                this.weaponname = this.owner.weaponname;
                this.dmg = this.owner.modelindex;
                this.deadflag = this.owner.deadflag;
 
-               CL_WeaponEntity_SetModel(this, weaponentity, this.owner.weaponname);
+               CL_WeaponEntity_SetModel(this, this.owner.weaponname);
        }
 
-       int tb = (this.effects & (EF_TELEPORT_BIT | EF_RESTARTANIM_BIT));
-       this.effects = this.owner.effects & EFMASK_CHEAP;
-       this.effects &= ~EF_LOWPRECISION;
-       this.effects &= ~EF_FULLBRIGHT;  // can mask team color, so get rid of it
-       this.effects &= ~EF_TELEPORT_BIT;
-       this.effects &= ~EF_RESTARTANIM_BIT;
-       this.effects |= tb;
-       if (weaponentity != weaponentities[0]) this.effects |= EF_NODRAW;
+       this.alpha = -1;  // TODO: don't render this entity at all
 
-       if (this.owner.alpha == default_player_alpha) this.alpha = default_weapon_alpha;
-       else if (this.owner.alpha != 0) this.alpha = this.owner.alpha;
-       else this.alpha = 1;
+       if (this.owner.alpha == default_player_alpha) this.m_alpha = default_weapon_alpha;
+       else if (this.owner.alpha != 0) this.m_alpha = this.owner.alpha;
+       else this.m_alpha  = 1;
 
-       this.glowmod = this.owner.weaponentity_glowmod;
-       this.colormap = this.owner.colormap;
-       if (this.(weaponentity))
-       {
-               this.(weaponentity).effects = this.effects;
-               this.(weaponentity).alpha = this.alpha;
-               this.(weaponentity).colormap = this.colormap;
-               this.(weaponentity).glowmod = this.glowmod;
-       }
-
-       this.angles = '0 0 0';
-
-       float f = this.weapon_nextthink - time;
-       if (this.state == WS_RAISE && !intermission_running)
-       {
-               entity newwep = Weapons_from(this.owner.switchweapon);
-               f = f * g_weaponratefactor / max(f, newwep.switchdelay_raise);
-               this.angles_x = -90 * f * f;
-       }
-       else if (this.state == WS_DROP && !intermission_running)
-       {
-               entity oldwep = Weapons_from(this.owner.weapon);
-               f = 1 - f * g_weaponratefactor / max(f, oldwep.switchdelay_drop);
-               this.angles_x = -90 * f * f;
-       }
-       else if (this.state == WS_CLEAR)
+       if (this.weaponchild)
        {
-               f = 1;
-               this.angles_x = -90 * f * f;
+               this.weaponchild.alpha = this.alpha;
+               this.weaponchild.effects = this.effects;
        }
 }
 
@@ -443,31 +154,27 @@ void CL_ExteriorWeaponentity_Think()
 }
 
 // spawning weaponentity for client
-void CL_SpawnWeaponentity(entity e, .entity weaponentity)
+void CL_SpawnWeaponentity(entity actor, .entity weaponentity)
 {
-       entity view = e.(weaponentity) = new(weaponentity);
+       entity view = actor.(weaponentity) = new(weaponentity);
        make_pure(view);
        view.solid = SOLID_NOT;
-       view.owner = e;
+       view.owner = actor;
        setmodel(view, MDL_Null);  // precision set when changed
        setorigin(view, '0 0 0');
-       view.angles = '0 0 0';
-       view.viewmodelforclient = e;
-       view.flags = 0;
        view.weaponentity_fld = weaponentity;
        view.think = CL_Weaponentity_Think;
-       view.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
        view.nextthink = time;
+       view.viewmodelforclient = actor;
+       view.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
 
        if (weaponentity == weaponentities[0])
        {
-               entity exterior = e.exteriorweaponentity = new(exteriorweaponentity);
+               entity exterior = actor.exteriorweaponentity = new(exteriorweaponentity);
                make_pure(exterior);
                exterior.solid = SOLID_NOT;
-               exterior.exteriorweaponentity = exterior;
-               exterior.owner = e;
+               exterior.owner = actor;
                setorigin(exterior, '0 0 0');
-               exterior.angles = '0 0 0';
                exterior.think = CL_ExteriorWeaponentity_Think;
                exterior.nextthink = time;
 
@@ -513,7 +220,7 @@ bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary
                        if (mine.owner == actor) return false;
 
        if (thiswep == WEP_SHOTGUN)
-               if (!secondary && WEP_CVAR(shotgun, secondary) == 1) return false;             // no clicking, just allow
+               if (!secondary && WEP_CVAR(shotgun, secondary) == 1) return false;           // no clicking, just allow
 
        if (thiswep == Weapons_from(actor.switchweapon) && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
        {
@@ -608,7 +315,13 @@ bool weapon_prepareattack(Weapon thiswep, entity actor, .entity weaponentity, bo
        return false;
 }
 
-void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(Weapon thiswep, entity actor,
+void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim);
+
+/**
+ * @param t defer thinking until time + t
+ * @param func next think function
+ */
+void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,
        .entity weaponentity, int fire) func)
 {
        entity this = actor.(weaponentity);
@@ -618,30 +331,25 @@ void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(W
                fr = this.wframe;
                restartanim = false;
        }
-       else if (fr == WFRAME_IDLE)
-       {
-               restartanim = false;
-       }
        else
        {
-               restartanim = true;
+               restartanim = fr != WFRAME_IDLE;
        }
 
        vector of = v_forward;
        vector or = v_right;
        vector ou = v_up;
 
+       vector a = '0 0 0';
        if (this)
        {
                this.wframe = fr;
-               vector a = '0 0 0';
                if (fr == WFRAME_IDLE) a = this.anim_idle;
                else if (fr == WFRAME_FIRE1) a = this.anim_fire1;
                else if (fr == WFRAME_FIRE2) a = this.anim_fire2;
                else  // if (fr == WFRAME_RELOAD)
                        a = this.anim_reload;
                a.z *= g_weaponratefactor;
-               setanim(this, a, restartanim == false, restartanim, restartanim);
        }
 
        v_forward = of;
@@ -665,20 +373,28 @@ void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(W
                this.weapon_nextthink = time;
                // dprint("reset weapon animation timer at ", ftos(time), "\n");
        }
-       this.weapon_nextthink = this.weapon_nextthink + t;
+       this.weapon_nextthink += t;
+       if (weaponentity == weaponentities[0]) STAT(WEAPON_NEXTTHINK, actor) = this.weapon_nextthink;
        this.weapon_think = func;
        // dprint("next ", ftos(this.weapon_nextthink), "\n");
 
+       if (this)
+       {
+               entity e;
+               FOR_EACH_CLIENT(e) if (e == actor || (IS_SPEC(e) && e.enemy == actor)) wframe_send(e, this, a, restartanim);
+       }
+
        if ((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
        {
-               if ((actor.weapon == WEP_SHOCKWAVE.m_id || actor.weapon == WEP_SHOTGUN.m_id)
-                   && fr == WFRAME_FIRE2) animdecide_setaction(actor, ANIMACTION_MELEE, restartanim);
-               else animdecide_setaction(actor, ANIMACTION_SHOOT, restartanim);
+               int act = (fr == WFRAME_FIRE2 && (actor.weapon == WEP_SHOCKWAVE.m_id || actor.weapon == WEP_SHOTGUN.m_id))
+                       ? ANIMACTION_MELEE
+                       : ANIMACTION_SHOOT
+                       ;
+               animdecide_setaction(actor, act, restartanim);
        }
-       else
+       else if (actor.anim_upper_action == ANIMACTION_SHOOT || actor.anim_upper_action == ANIMACTION_MELEE)
        {
-               if (actor.anim_upper_action == ANIMACTION_SHOOT
-                   || actor.anim_upper_action == ANIMACTION_MELEE) actor.anim_upper_action = 0;
+               actor.anim_upper_action = 0;
        }
 }
 
@@ -696,11 +412,11 @@ bool forbidWeaponUse(entity player)
 
 void W_WeaponFrame(entity actor)
 {
-       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       .entity weaponentity = weaponentities[0];  // TODO: unhardcode
        entity this = actor.(weaponentity);
        if (frametime) actor.weapon_frametime = frametime;
 
-       if (!this || actor.health < 1) return; // Dead player can't use weapons and injure impulse commands
+       if (!this || actor.health < 1) return;  // Dead player can't use weapons and injure impulse commands
 
 
        if (forbidWeaponUse(actor))
@@ -780,13 +496,7 @@ void W_WeaponFrame(entity actor)
                                entity oldwep = Weapons_from(actor.weapon);
 
                                // set up weapon switch think in the future, and start drop anim
-                               if (
-#if INDEPENDENT_ATTACK_FINISHED
-                                           true
-#else
-                                           ATTACK_FINISHED(actor, slot) <= time + actor.weapon_frametime * 0.5
-#endif
-                                  )
+                               if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponslot(weaponentity)) <= time + actor.weapon_frametime * 0.5)
                                {
                                        sound(actor, CH_WEAPON_SINGLE, SND_WEAPON_SWITCH, VOL_BASE, ATTN_NORM);
                                        this.state = WS_DROP;
@@ -808,7 +518,7 @@ void W_WeaponFrame(entity actor)
        // server framerate is very low and the weapon fire rate very high
        for (int c = 0; c < W_TICSPERFRAME; ++c)
        {
-               if (w && !(actor.weapons & WepSet_FromWeapon(w)))
+               if (w && !(actor.weapons & WepSet_FromWeapon(Weapons_from(w))))
                {
                        if (actor.weapon == actor.switchweapon) W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
                        w = 0;
@@ -880,9 +590,11 @@ void W_AttachToShotorg(entity actor, entity flash, vector offset)
        flash.owner = actor;
        flash.angles_z = random() * 360;
 
-       entity this = actor.(weaponentity);
-       if (gettagindex(this, "shot")) setattachment(flash, this, "shot");
-       else setattachment(flash, this, "tag_shot");
+       entity view = actor.(weaponentity);
+       entity exterior = actor.exteriorweaponentity;
+
+       if (gettagindex(view, "shot")) setattachment(flash, view, "shot");
+       else setattachment(flash, view, "tag_shot");
        setorigin(flash, offset);
 
        entity xflash = spawn();
@@ -890,15 +602,15 @@ void W_AttachToShotorg(entity actor, entity flash, vector offset)
 
        flash.viewmodelforclient = actor;
 
-       if (this.oldorigin.x > 0)
+       if (view.oldorigin.x > 0)
        {
-               setattachment(xflash, actor.exteriorweaponentity, "");
-               setorigin(xflash, this.oldorigin + offset);
+               setattachment(xflash, exterior, "");
+               setorigin(xflash, view.oldorigin + offset);
        }
        else
        {
-               if (gettagindex(actor.exteriorweaponentity, "shot")) setattachment(xflash, actor.exteriorweaponentity, "shot");
-               else setattachment(xflash, actor.exteriorweaponentity, "tag_shot");
+               if (gettagindex(exterior, "shot")) setattachment(xflash, exterior, "shot");
+               else setattachment(xflash, exterior, "tag_shot");
                setorigin(xflash, offset);
        }
 }
index 97e6c72b4be3698caee7cfca657bf4fd4858c4f2..0000ac2155b762298e15bbb956187955cbec7fb5 100644 (file)
@@ -1,23 +1,11 @@
 #ifndef WEAPONSYSTEM_H
 #define WEAPONSYSTEM_H
 
-.float wframe;
 
 float internalteam;
 float weaponswapping;
 entity weapon_dropevent_item;
 
-// VorteX: static frame globals
-const float WFRAME_DONTCHANGE = -1;
-const float WFRAME_FIRE1 = 0;
-const float WFRAME_FIRE2 = 1;
-const float WFRAME_IDLE = 2;
-const float WFRAME_RELOAD = 3;
-
-vector shotorg_adjust(vector vecs, bool y_is_right, bool visual, int algn);
-
-vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
-
 void CL_SpawnWeaponentity(entity e, .entity weaponentity);
 
 vector CL_Weapon_GetShotOrg(float wpn);
@@ -44,6 +32,6 @@ bool weapon_prepareattack_check(Weapon thiswep, entity actor, .entity weaponenti
 
 void weapon_prepareattack_do(entity actor, .entity weaponentity, float secondary, float attacktime);
 
-void weapon_thinkf(entity actor, .entity weaponentity, float fr, float t, void(Weapon thiswep, entity actor, .entity weaponentity, int fire) func);
+void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor, .entity weaponentity, int fire) func);
 
 #endif