]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Lyberta/TeamplayOverhaul
authorLyberta <lyberta@lyberta.net>
Sun, 11 Mar 2018 06:06:40 +0000 (09:06 +0300)
committerLyberta <lyberta@lyberta.net>
Sun, 11 Mar 2018 06:06:40 +0000 (09:06 +0300)
gfx/hud/default/nade_veil.tga [new file with mode: 0644]
gfx/hud/luma/nade_veil.tga [new file with mode: 0644]
mutators.cfg
qcsrc/common/mutators/mutator/nades/nades.inc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/nades/nades.qh
qcsrc/common/stats.qh
qcsrc/lib/color.qh
qcsrc/lib/spawnfunc.qh
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/server/autocvars.qh

diff --git a/gfx/hud/default/nade_veil.tga b/gfx/hud/default/nade_veil.tga
new file mode 100644 (file)
index 0000000..3134d1b
Binary files /dev/null and b/gfx/hud/default/nade_veil.tga differ
diff --git a/gfx/hud/luma/nade_veil.tga b/gfx/hud/luma/nade_veil.tga
new file mode 100644 (file)
index 0000000..edb66b5
Binary files /dev/null and b/gfx/hud/luma/nade_veil.tga differ
index ff5cf3223d1050efcb6a8e2b194297b6ae234206..32145dd04c8128f7e65b24d7a0c752d2d9b6cc7c 100644 (file)
@@ -198,7 +198,7 @@ set g_nades_nade_edgedamage 90
 set g_nades_nade_radius 300
 set g_nades_nade_force 650
 set g_nades_nade_newton_style 0 "0 is absolute, 1 is relative (takes into account player speed), 2 is something in between"
-set g_nades_nade_type 1 "Type of the off-hand grenade. 1:normal 2:napalm 3:ice 4:translocate 5:spawn 6:heal 7:pokenade 8:entrap"
+set g_nades_nade_type 1 "Type of the off-hand grenade. 1:normal 2:napalm 3:ice 4:translocate 5:spawn 6:heal 7:pokenade 8:entrap 9:veil"
 
 seta cl_nade_timer 1 "show a visual timer for nades, 1 = only circle, 2 = circle with text"
 seta cl_nade_type 3
@@ -216,7 +216,7 @@ seta cl_pokenade_type "zombie"
 //
 set g_nades_bonus 0 "Enable bonus grenades"
 set g_nades_bonus_client_select 0 "Allow client side selection of bonus nade type"
-set g_nades_bonus_type 2 "Type of the bonus grenade. 1:normal 2:napalm 3:ice 4:translocate 5:spawn 6:heal 7:pokenade 8:entrap"
+set g_nades_bonus_type 2 "Type of the bonus grenade. 1:normal 2:napalm 3:ice 4:translocate 5:spawn 6:heal 7:pokenade 8:entrap 9:veil"
 set g_nades_bonus_onstrength 1 "Always give bonus grenades to players that have the strength powerup"
 set g_nades_bonus_max 3 "Maximum number of bonus grenades"
 set g_nades_bonus_only 0 "Disallow regular nades, only bonus nades can be used"
@@ -274,6 +274,10 @@ set g_nades_entrap_speed 0.5 "Running speed while entrapped"
 set g_nades_entrap_time 10 "Life time of the orb"
 set g_nades_entrap_radius 500
 
+// Veil (9)
+set g_nades_veil_time 8 "Life time of the orb"
+set g_nades_veil_radius 300
+
 
 // ============
 //  camp check
index bcdbe0cd920973e256c142f27d1d216ef8e90f02..0245cee640f1e9437af91804340e9f0fbb737ba3 100644 (file)
@@ -68,3 +68,12 @@ REGISTER_NADE(ENTRAP) {
     NADE_PROJECTILE(0, PROJECTILE_NADE_ENTRAP, EFFECT_NADE_TRAIL_YELLOW);
     NADE_PROJECTILE(1, PROJECTILE_NADE_ENTRAP_BURN, EFFECT_NADE_TRAIL_BURN_YELLOW);
 }
+
+REGISTER_NADE(VEIL) {
+    this.m_color = '0.65 0.85 0.65';
+    this.m_name = _("Veil grenade");
+    this.m_icon = "nade_veil";
+    this.m_alpha = 0.45;
+    NADE_PROJECTILE(0, PROJECTILE_NADE_VEIL, EFFECT_NADE_TRAIL_NEUTRAL);
+    NADE_PROJECTILE(1, PROJECTILE_NADE_VEIL_BURN, EFFECT_NADE_TRAIL_BURN_NEUTRAL);
+}
index 24149ad7fce9430ca89000e777d20a3939f25fe6..1ffce5daed8986b7b5c420d8d40dfb88b3b9cd29 100644 (file)
@@ -36,6 +36,7 @@ entity Nade_TrailEffect(int proj, int nade_team)
 REGISTER_MUTATOR(cl_nades, true);
 MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay)
 {
+       // TODO: make a common orb state!
        if (STAT(HEALING_ORB) > time)
        {
                M_ARGV(0, vector) = NADE_TYPE_HEAL.m_color;
@@ -48,6 +49,12 @@ MUTATOR_HOOKFUNCTION(cl_nades, HUD_Draw_overlay)
                M_ARGV(1, float) = STAT(ENTRAP_ORB_ALPHA);
                return true;
        }
+       if (STAT(VEIL_ORB) > time)
+       {
+               M_ARGV(0, vector) = NADE_TYPE_VEIL.m_color;
+               M_ARGV(1, float) = STAT(VEIL_ORB_ALPHA);
+               return true;
+       }
        return false;
 }
 MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
@@ -96,6 +103,7 @@ MUTATOR_HOOKFUNCTION(cl_nades, EditProjectile)
        settouch(proj, func_null);
        proj.scale = 1.5;
        proj.avelocity = randomvec() * 720;
+       proj.alphamod = nade_type.m_alpha;
 
        if (nade_type == NADE_TYPE_TRANSLOCATE || nade_type == NADE_TYPE_SPAWN)
                proj.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
@@ -665,6 +673,35 @@ void nade_monster_boom(entity this)
        e.monster_skill = MONSTER_SKILL_INSANE;
 }
 
+void nade_veil_touch(entity this, entity toucher)
+{
+       if ( IS_REAL_CLIENT(toucher) || IS_VEHICLE(toucher) || IS_MONSTER(toucher) )
+       {
+               entity show_tint = (IS_VEHICLE(toucher)) ? toucher.owner : toucher;
+
+               float tint_alpha = 0.75;
+               if(SAME_TEAM(toucher, this.realowner))
+               {
+                       tint_alpha = 0.45;
+                       if(!STAT(VEIL_ORB, show_tint))
+                       {
+                               toucher.nade_veil_prevalpha = toucher.alpha;
+                               toucher.alpha = -1;
+                       }
+               }
+               STAT(VEIL_ORB, show_tint) = time + 0.1;
+               STAT(VEIL_ORB_ALPHA, show_tint) = tint_alpha * (this.ltime - time) / this.orb_lifetime;
+       }
+}
+
+void nade_veil_boom(entity this)
+{
+       entity orb = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_veil_time, autocvar_g_nades_veil_radius);
+
+       settouch(orb, nade_veil_touch);
+       orb.colormod = NADE_TYPE_VEIL.m_color;
+}
+
 void nade_boom(entity this)
 {
        entity expef = NULL;
@@ -705,6 +742,11 @@ void nade_boom(entity this)
                        expef = EFFECT_SPAWN_YELLOW;
                        break;
 
+               case NADE_TYPE_VEIL:
+                       nade_blast = false;
+                       expef = EFFECT_SPAWN_NEUTRAL;
+                       break;
+
                default:
                case NADE_TYPE_NORMAL:
                        expef = EFFECT_NADE_EXPLODE(this.realowner.team);
@@ -736,6 +778,7 @@ void nade_boom(entity this)
                case NADE_TYPE_HEAL: nade_heal_boom(this); break;
                case NADE_TYPE_MONSTER: nade_monster_boom(this); break;
                case NADE_TYPE_ENTRAP: nade_entrap_boom(this); break;
+               case NADE_TYPE_VEIL: nade_veil_boom(this); break;
        }
 
        IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
@@ -1056,6 +1099,7 @@ void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, strin
        n.projectiledeathtype = DEATH_NADE.m_id;
        n.weaponentity_fld = weaponentity;
        n.nade_lifetime = ntime;
+       n.alpha = Nades_from(STAT(NADE_BONUS_TYPE, n)).m_alpha;
 
        setmodel(fn, MDL_NADE_VIEW);
        setattachment(fn, player.(weaponentity), "");
@@ -1066,6 +1110,7 @@ void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, strin
        setthink(fn, SUB_Remove);
        fn.nextthink = n.wait;
        fn.weaponentity_fld = weaponentity;
+       fn.alpha = Nades_from(STAT(NADE_BONUS_TYPE, n)).m_alpha;
 
        player.nade = n;
        player.fake_nade = fn;
@@ -1271,6 +1316,15 @@ MUTATOR_HOOKFUNCTION(nades, PlayerPreThink)
                {
                        STAT(NADE_BONUS, player) = STAT(NADE_BONUS_SCORE, player) = 0;
                }
+
+               if(STAT(VEIL_ORB, player) && STAT(VEIL_ORB, player) <= time)
+               {
+                       STAT(VEIL_ORB, player) = 0;
+                       if(player.vehicle)
+                               player.vehicle.alpha = player.vehicle.nade_veil_prevalpha;
+                       else
+                               player.alpha = player.nade_veil_prevalpha;
+               }
        }
 
        int n = 0;
@@ -1331,6 +1385,12 @@ MUTATOR_HOOKFUNCTION(nades, MonsterMove)
                M_ARGV(1, float) *= autocvar_g_nades_entrap_speed; // run speed
                M_ARGV(2, float) *= autocvar_g_nades_entrap_speed; // walk speed
        }
+
+       if (STAT(VEIL_ORB, mon) && STAT(VEIL_ORB, mon) <= time)
+       {
+               mon.alpha = mon.nade_veil_prevalpha;
+               STAT(VEIL_ORB, mon) = 0;
+       }
 }
 
 MUTATOR_HOOKFUNCTION(nades, PlayerSpawn)
@@ -1404,10 +1464,7 @@ MUTATOR_HOOKFUNCTION(nades, Damage_Calculate)
        entity frag_target = M_ARGV(2, entity);
        float frag_deathtype = M_ARGV(3, float);
 
-       if(STAT(FROZEN, frag_target))
-       if(autocvar_g_freezetag_revive_nade)
-       if(frag_attacker == frag_target)
-       if(frag_deathtype == DEATH_NADE.m_id)
+       if(autocvar_g_freezetag_revive_nade && STAT(FROZEN, frag_target) && frag_attacker == frag_target && frag_deathtype == DEATH_NADE.m_id)
        if(time - frag_inflictor.toss_time <= 0.1)
        {
                Unfreeze(frag_target);
@@ -1469,6 +1526,8 @@ MUTATOR_HOOKFUNCTION(nades, SpectateCopy)
        STAT(HEALING_ORB_ALPHA, client) = STAT(HEALING_ORB_ALPHA, spectatee);
        STAT(ENTRAP_ORB, client) = STAT(ENTRAP_ORB, spectatee);
        STAT(ENTRAP_ORB_ALPHA, client) = STAT(ENTRAP_ORB_ALPHA, spectatee);
+       STAT(VEIL_ORB, client) = STAT(VEIL_ORB, spectatee);
+       STAT(VEIL_ORB_ALPHA, client) = STAT(VEIL_ORB_ALPHA, spectatee);
 }
 
 REPLICATE(cvar_cl_nade_type, int, "cl_nade_type");
index c5a1967e0b53ffa14bd4e0e756070cf7fb584802..e109fa7a35ddbddab0f90e18357a8a72daccbc30 100644 (file)
@@ -18,6 +18,8 @@ const int PROJECTILE_NADE_MONSTER = 82;
 const int PROJECTILE_NADE_MONSTER_BURN = 83;
 const int PROJECTILE_NADE_ENTRAP = 84;
 const int PROJECTILE_NADE_ENTRAP_BURN = 85;
+const int PROJECTILE_NADE_VEIL = 86;
+const int PROJECTILE_NADE_VEIL_BURN = 87;
 
 REGISTRY(Nades, BITS(4))
 #define Nades_from(i) _Nades_from(i, NADE_TYPE_Null)
@@ -31,6 +33,7 @@ CLASS(Nade, Object)
     ATTRIB(Nade, m_color, vector, '0 0 0');
     ATTRIB(Nade, m_name, string, _("Grenade"));
     ATTRIB(Nade, m_icon, string, "nade_normal");
+    ATTRIB(Nade, m_alpha, float, 1);
     ATTRIBARRAY(Nade, m_projectile, int, 2);
     ATTRIBARRAY(Nade, m_trail, entity, 2);
     METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) {
@@ -72,6 +75,7 @@ Nade Nade_FromProjectile(int proj)
 .string cvar_cl_pokenade_type;
 .float toss_time;
 .float nade_show_particles;
+.float nade_veil_prevalpha;
 
 bool orb_send(entity this, entity to, int sf);
 
index 648ef60e844b8f316662ea633e5c6ac3ca2a12dc..9b8f04041780fd55f707331540c74ab99b0e8e88 100644 (file)
@@ -120,6 +120,8 @@ REGISTER_STAT(ENTRAP_ORB, float)
 REGISTER_STAT(ENTRAP_ORB_ALPHA, float)
 REGISTER_STAT(ITEMSTIME, int, autocvar_sv_itemstime)
 REGISTER_STAT(KILL_TIME, float)
+REGISTER_STAT(VEIL_ORB, float)
+REGISTER_STAT(VEIL_ORB_ALPHA, float)
 
 #ifdef SVQC
 float autocvar_sv_showfps = 5;
index 5f9297f2dab1f5be24887ff2fead30390ee59fd6..6f7a7326de41f5cce1953dc26a5ac27aa933296d 100644 (file)
@@ -25,13 +25,13 @@ vector colormapPaletteColor_(int c, bool isPants, float t)
                case 14: return '1.000000 0.666667 0.000000';
                case 15:
                        if (isPants)
-                               return '1 0 0' * (0.502 + 0.498 * sin(t / 2.7182818285 + 0.0000000000))
-                                      + '0 1 0' * (0.502 + 0.498 * sin(t / 2.7182818285 + 2.0943951024))
-                                      + '0 0 1' * (0.502 + 0.498 * sin(t / 2.7182818285 + 4.1887902048));
+                               return '1 0 0' * (0.502 + 0.498 * sin(t / M_E + 0))
+                                       + '0 1 0' * (0.502 + 0.498 * sin(t / M_E + M_PI * 2 / 3))
+                                       + '0 0 1' * (0.502 + 0.498 * sin(t / M_E + M_PI * 4 / 3));
                        else
-                               return '1 0 0' * (0.502 + 0.498 * sin(t / 3.1415926536 + 5.2359877560))
-                                      + '0 1 0' * (0.502 + 0.498 * sin(t / 3.1415926536 + 3.1415926536))
-                                      + '0 0 1' * (0.502 + 0.498 * sin(t / 3.1415926536 + 1.0471975512));
+                               return '1 0 0' * (0.502 + 0.498 * sin(t / M_PI + M_PI * 5 / 3))
+                                       + '0 1 0' * (0.502 + 0.498 * sin(t / M_PI + M_PI))
+                                       + '0 0 1' * (0.502 + 0.498 * sin(t / M_PI + M_PI * 1 / 3));
                default: return '0.000 0.000 0.000';
        }
 }
index ac9ad505801b76edce158c34b8e3176c369e7c71..e14002a6d5b3812f59533e82ae5346463a610ec5 100644 (file)
@@ -19,13 +19,13 @@ noref bool require_spawnfunc_prefix;
        }
 
        #define _spawnfunc_checktypes(fld) \
-               if (fieldname == #fld) \
-                       if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted", fieldname);
+               if (s == #fld) \
+                       if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted", s);
 #else
        #define _spawnfunc_checktypes(fld)
 #endif
        #define _spawnfunc_check(fld) \
-               if (fieldname == #fld) continue;
+               if (s == #fld) continue;
 
        noref int __spawnfunc_expecting;
        noref entity __spawnfunc_expect;
@@ -111,13 +111,13 @@ noref bool require_spawnfunc_prefix;
                        if (!this.spawnfunc_checked) { \
                                for (int i = 0, n = numentityfields(); i < n; ++i) { \
                                        string value = getentityfieldstring(i, this); \
-                                       string fieldname = entityfieldname(i); \
+                                       string s = entityfieldname(i); \
                                        whitelist(_spawnfunc_checktypes) \
                                        if (value == "") continue; \
-                                       if (fieldname == "") continue; \
+                                       if (s == "") continue; \
                                        FIELDS_COMMON(_spawnfunc_check) \
                                        whitelist(_spawnfunc_check) \
-                                       LOG_WARNF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue."), #id, fieldname, value); \
+                                       LOG_WARNF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue."), #id, s, value); \
                                } \
                                this.spawnfunc_checked = true; \
                                if (this) { \
@@ -262,7 +262,6 @@ noref bool require_spawnfunc_prefix;
                FIELD_VEC(fld, color) \
                FIELD_VEC(fld, mangle) \
                FIELD_VEC(fld, maxs) \
-               FIELD_VEC(fld, maxs) \
                FIELD_VEC(fld, mins) \
                FIELD_VEC(fld, modelscale_vec) \
                FIELD_VEC(fld, velocity) \
index 63b55a19b9514200ab86e1fe3e298afb7aea5a22..022bed03d52912ce05e35a245f0dba12255524ae 100644 (file)
@@ -241,32 +241,40 @@ void XonoticMutatorsDialog_fill(entity me)
 
        me.gotoRC(me, 0, 2); me.setFirstColumn(me, me.currentColumn);
                me.TD(me, 1, 2, e = makeXonoticRadioButton(1, string_null, string_null, _("Regular (no arena)")));
+       string weaponarena_tooltip = strzone(_("Players will be given a set of weapons at spawn as well as unlimited ammo, without weapon pickups"));
        me.TR(me);
-               me.TD(me, 1, 2, e = makeXonoticRadioButton_T(1, "g_weaponarena", "menu_weaponarena", _("Weapon arenas:"),
-                       _("Selecting a weapon arena will give all players that weapon at spawn as well as unlimited ammo, and disable all other weapon pickups.")));
+               me.TD(me, 1, 2, makeXonoticTextLabel(0, _("Weapon arenas:")));
+       me.TR(me);
+               me.TDempty(me, 0.2);
+               me.TD(me, 1, 1.8, e = makeXonoticRadioButton_T(1, "g_weaponarena", "menu_weaponarena", _("Custom weapons"), weaponarena_tooltip));
                        e.cvarValueIsAnotherCvar = true;
                        e.cvarOffValue = "0";
+
+               me.TDempty(me, 0.1); // fix initial position
        for(i = WEP_FIRST, j = 0; i <= WEP_LAST; ++i)
        {
                w = Weapons_from(i);
                if(w.spawnflags & WEP_FLAG_HIDDEN)
                        continue;
                if((j & 1) == 0)
+                       me.TDempty(me, 0.2);
+               else
+               {
                        me.TR(me);
-               me.TDempty(me, 0.2);
-               me.TD(me, 1, 1.8, e = makeXonoticWeaponarenaCheckBox(strzone(w.netname), strzone(w.m_name)));
+                       me.TDempty(me, 0.4);
+               }
+               me.TD(me, 1, 1.7, e = makeXonoticWeaponarenaCheckBox(strzone(w.netname), strzone(w.m_name)));
                        setDependentWeird(e, checkCompatibility_weaponarena_weapon);
                ++j;
        }
+
        me.TR(me);
                me.TDempty(me, 0.2);
-               me.TD(me, 1, 1.8, e = makeXonoticRadioButton_T(1, "g_weaponarena", "most", _("Most weapons"),
-                       _("Selecting a weapon arena will give all players that weapon at spawn as well as unlimited ammo, and disable all other weapon pickups.")));
+               me.TD(me, 1, 1.8, e = makeXonoticRadioButton_T(1, "g_weaponarena", "most", _("Most weapons"), weaponarena_tooltip));
                        e.cvarOffValue = "0";
        me.TR(me);
                me.TDempty(me, 0.2);
-               me.TD(me, 1, 1.8, e = makeXonoticRadioButton_T(1, "g_weaponarena", "all", _("All weapons"),
-                       _("Selecting a weapon arena will give all players that weapon at spawn as well as unlimited ammo, and disable all other weapon pickups.")));
+               me.TD(me, 1, 1.8, e = makeXonoticRadioButton_T(1, "g_weaponarena", "all", _("All weapons"), weaponarena_tooltip));
                        e.cvarOffValue = "0";
        me.TR(me);
                me.TD(me, 1, 4, makeXonoticTextLabel(0, _("Special arenas:")));
index a2f9ab49b4f9c48497e8599806adc6ff7cd247a2..e9bacafa7d1ffd650045e23cded798ce46cbcce5 100644 (file)
@@ -470,6 +470,8 @@ float autocvar_g_nades_entrap_strength = 0.01;
 float autocvar_g_nades_entrap_speed = 0.5;
 float autocvar_g_nades_entrap_radius = 500;
 float autocvar_g_nades_entrap_time = 10;
+float autocvar_g_nades_veil_time = 8;
+float autocvar_g_nades_veil_radius = 300;
 string autocvar_g_nades_pokenade_monster_type;
 float autocvar_g_nades_pokenade_monster_lifetime;
 bool autocvar_g_jump_grunt;