Xonotic Forums
[SUGGESTION] TTS mode spawnshield - Printable Version

+- Xonotic Forums (https://forums.xonotic.org)
+-- Forum: Creating & Contributing (https://forums.xonotic.org/forumdisplay.php?fid=10)
+--- Forum: Xonotic - Suggestion Box (https://forums.xonotic.org/forumdisplay.php?fid=20)
+--- Thread: [SUGGESTION] TTS mode spawnshield (/showthread.php?tid=3694)



TTS mode spawnshield - -maniac|Su- - 11-24-2012

hi folks

is it possible to implement a spawnshield mode in Xonotic like the TTS mode in Nexuiz ... Huh

The TTS mode was created by Fish

The code was nearly:
Code:
Index: data/qcsrc/server/g_damage.qc
===================================================================
--- data/qcsrc/server/g_damage.qc    (revision 8003)
+++ data/qcsrc/server/g_damage.qc    (working copy)
@@ -370,12 +370,38 @@
                    }
                }

+                ///MODIFICATION///
+                local float fragsup, spawnfrag;
+                fragsup = 1;
+                spawnfrag = FALSE;
+                if (tts_spawnshield_mode != 0)
+                    if(time < targ.tts_spawnshieldfinished || (tts_spawnshield_mode == 2 && time < attacker.tts_spawnshieldfinished)) {    
+                        fragsup = 0;
+                        spawnfrag = TRUE;
+                    }
+                if (targ.classname=="corpse")
+                    fragsup = 0;
+
+                local string typefragremark;
+                local string spawnfragremark;
+                
+                if (targ.buttonchat) typefragremark = "^7type";
+                else typefragremark = "";
+                if (spawnfrag) spawnfragremark = "^2spawn";
+                else spawnfragremark = "";
+
+
                if(sv_gentle > 0) {
-                    centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, "^4You scored against ^7", s));
+                    centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, blood_message, "^4You scored against ^7", s));
                    centerprint(targ, strcat(DAMAGE_CENTERPRINT_SPACER, a,"^1 scored against you ^7"));
                } else {
-                    centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, blood_message, "^4You fragged ^7", s));
-                    centerprint(targ, strcat(DAMAGE_CENTERPRINT_SPACER, victim_message, "^1You were fragged by ^7", a));
+                    if((cvar("sv_fragmessage_information_typefrag")) && (targ.BUTTON_CHAT)) {
+                        centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, blood_message, "^4You ^1typefragged ^7", s));
+                        centerprint(targ, strcat(DAMAGE_CENTERPRINT_SPACER, victim_message, "^1You were typefragged by ^7", a));
+                    } else {
+                        centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, blood_message, "^4You ",spawnfragremark, typefragremark,"^4fragged ^7", s));
+                                                centerprint(targ, strcat(DAMAGE_CENTERPRINT_SPACER, victim_message, "^1You were ",spawnfragremark, typefragremark, "^1fragged by ^7", a));
+                    }
                    attacker.taunt_soundtime = time + 1;
                }

@@ -435,7 +461,7 @@
                    GiveFrags(attacker, targ, 0); // for logging
                }
                else
-                    GiveFrags(attacker, targ, 1);
+                    GiveFrags(attacker, targ, fragsup);

                if (targ.killcount > 2) {
                    if(sv_gentle)
@@ -713,6 +739,12 @@
                self = oldself;
                return;
            }
+
+            ///MODIFICATION///
+            if ((deathtype == WEP_MINSTANEX) && damage) {
+                attacker.tts_hits ++;
+            }
+
            if (targ.armorvalue && (deathtype == WEP_MINSTANEX) && damage)
            {
                targ.armorvalue -= 1;
Index: data/qcsrc/server/defs.qh
===================================================================
--- data/qcsrc/server/defs.qh    (revision 8003)
+++ data/qcsrc/server/defs.qh    (working copy)
@@ -623,3 +623,15 @@

.entity clientdata;
.entity personal;
+
+
+///MODIFICATION///
+.float tts_powerups_invis_fire_recoverfinished;
+.float tts_powerups_invis_fire_recoverduration;
+.float tts_powerups_invis_started;
+.float tts_spawnshieldfinished;
+.float tts_powerups_invis_nextflicker;
+.float tts_hits;
+.float tts_shotsfired;
+float tts_lockedgame;
+float tts_gamefrozen;
Index: data/qcsrc/server/w_minstanex.qc
===================================================================
--- data/qcsrc/server/w_minstanex.qc    (revision 8003)
+++ data/qcsrc/server/w_minstanex.qc    (working copy)
@@ -179,10 +179,27 @@
    {
        if (self.BUTTON_ATCK)
        {
-            if (weapon_prepareattack(0, cvar("g_balance_minstanex_refire")))
+            ///MODIFICATION///
+            local float refire_factor;
+            refire_factor = 1.0;
+            
+            local float actual_refire;
+            actual_refire = cvar("g_balance_minstanex_refire") * refire_factor;
+
+            if (tts_spawnshield_mode == 1 && time < self.tts_spawnshieldfinished)
+                self.tts_spawnshieldfinished = time;
+
+            if (weapon_prepareattack(0, actual_refire))
            {
                W_MinstaNex_Attack();
                weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_minstanex_animtime"), w_ready);
+                ///MODIFICATION///
+                if(g_minstagib && (self.items & IT_STRENGTH) && tts_powerups_invis_fire_recovertime>0) {
+                    self.tts_powerups_invis_fire_recoverfinished =
+                        time + tts_powerups_invis_fire_recovertime;
+                    self.tts_powerups_invis_fire_recoverduration = tts_powerups_invis_fire_recovertime;
+                }                
+                self.tts_shotsfired ++;
            }
        }
        else if (self.BUTTON_ATCK2)
Index: data/qcsrc/server/miscfunctions.qc
===================================================================
--- data/qcsrc/server/miscfunctions.qc    (revision 8003)
+++ data/qcsrc/server/miscfunctions.qc    (working copy)
@@ -1042,6 +1042,30 @@
float sv_autotaunt;
float sv_taunt;

+
+
+///MODIFICATION///
+// Not all tts_ cvars have a declarator here, but most do.
+// Some are read on the fly, especially the welcomemessage ones
+float tts_powerups_reuse;
+float tts_powerups_invis_claim;
+float tts_powerups_speed_claim;
+
+float tts_powerups_invis_cloaktime;
+float tts_powerups_invis_fire_recovertime;
+float tts_powerups_invis_fire_alpha;
+float tts_powerups_invis_flicker_average;
+float tts_powerups_invis_flicker_deviation;
+float tts_powerups_invis_flicker_duration;
+
+float tts_spawnshield_time;
+float tts_spawnshield_mode;
+
+float tts_laser_jumpinterval;
+
+
+
+
void readlevelcvars(void)
{
     g_bugrigs = cvar("g_bugrigs");
@@ -1168,6 +1192,24 @@
     if not(inWarmupStage)
         game_starttime                 = cvar("g_start_delay");

+
+    ///MODIFICATION///
+    tts_powerups_reuse = cvar("tts_powerups_reuse");
+    tts_powerups_invis_claim = cvar("tts_powerups_invis_claim");
+    tts_powerups_speed_claim = cvar("tts_powerups_speed_claim");
+    
+    tts_powerups_invis_cloaktime = cvar("tts_powerups_invis_cloaktime");
+    tts_powerups_invis_fire_recovertime = cvar("tts_powerups_invis_fire_recovertime");
+    tts_powerups_invis_fire_alpha = cvar("tts_powerups_invis_fire_alpha");
+    tts_powerups_invis_flicker_average = cvar("tts_powerups_invis_flicker_average");
+    tts_powerups_invis_flicker_deviation = cvar("tts_powerups_invis_flicker_deviation");
+    tts_powerups_invis_flicker_duration = cvar("tts_powerups_invis_flicker_duration");
+            
+    tts_spawnshield_time = cvar("tts_spawnshield_time");
+    tts_spawnshield_mode = cvar("tts_spawnshield_mode");
+    
+    tts_laser_jumpinterval = cvar("tts_laser_jumpinterval");
+
     readplayerstartcvars();
}

Index: data/qcsrc/server/cl_client.qc
===================================================================
--- data/qcsrc/server/cl_client.qc    (revision 8003)
+++ data/qcsrc/server/cl_client.qc    (working copy)
@@ -660,6 +660,10 @@
    }
    else
        self.frags = FRAGS_SPECTATOR;
+
+    ///MODIFICATION///
+    self.tts_hits = 0;
+    self.tts_shotsfired = 0;
}

float RestrictSkin(float s)
@@ -671,6 +675,104 @@
    return mod(s, 3);
}

+
+
+///MODIFICATION///
+
+float CountActivePlayers() {
+    local entity pl;
+    local float plcnt;
+    local float countbots;
+    if(cvar("tts_gamecommencing_botsareplayers")) {
+        FOR_EACH_PLAYER(pl) plcnt+=1;
+    } else {
+        FOR_EACH_REALPLAYER(pl) plcnt+=1;
+    }
+    return plcnt;
+}
+
+void GameCommencing_Think() {
+    local float plcnt;
+    local entity pl;
+    local entity oldself;
+    
+    // Count number of players again, as they may have
+    // changed since the entity was created.
+    plcnt = CountActivePlayers();
+    
+    //bprint("^1DEBUG: ^3GameCommencing entity think\n");
+    
+    if(plcnt >= 2) {
+        // Output an info message in the console
+        print("^3Second player joined, starting game.\n");
+        
+        // Respawn each player and reset their score
+        FOR_EACH_PLAYER(pl) {
+            oldself = self;
+            self = pl;
+            if(self.flagcarried)
+                DropFlag(self.flagcarried, world, world);
+            self.frags = 0;
+            //self.deaths = 0;
+            self.killcount = 0;
+            //self.tts_kills = 0;
+            //self.tts_suicides = 0;
+            self.tts_hits = 0;
+            self.tts_shotsfired = 0;
+            PlayerScore_Clear(self);
+            PutClientInServer();
+            self = oldself;
+        }
+        
+        // Respawn all items
+        local entity it;
+        for(it=find(world,classname,"minstagib");it!=world;it=find(it,classname,"minstagib")) {
+            // NOTE: Checking for think is paramount! If think is not set,
+            // but nextthink is changed, the server ABORTS!
+            if(it.think)
+                it.nextthink = time;
+        }
+        
+        // Remove dropped weapons
+        for(it=find(world,classname,"droppedweapon");it!=world;it=find(it,classname,"droppedweapon")) {
+            it.think = RemoveItem;
+            it.nextthink = time;
+        }
+    }
+    
+    // Were no longer needed.
+    remove(self);
+}
+
+// Well, I tried to be as descriptive as possible in the function's name
+// It's supposed to be called on player join. If it counts 2 active players,
+// it respawns all players. (Counter-Strike style "Game Commencing")
+void OnJoinCheckAndRespawn() {
+    if(!cvar("tts_gamecommencing") || !g_minstagib) return;
+    
+    local float plcnt;
+    
+    // Count active players
+    plcnt = CountActivePlayers();
+    
+    //bprint(strcat("^1DEBUG: ^3Player count now ",ftos(plcnt),"\n"));
+    
+    if(plcnt==2) {
+        bcenterprint("^3Game commencing...\n");
+        local entity gamecommencing;
+        
+        // Do not spawn game-commencing entity if one already exists
+        if( (gamecommencing=find(world,classname,"gamecommencing_entity")) == world )
+            gamecommencing = spawn();
+        
+        gamecommencing.owner = world;
+        gamecommencing.classname = "gamecommencing_entity";
+        gamecommencing.think = GameCommencing_Think;
+        gamecommencing.nextthink = time + cvar("tts_gamecommencing_delay");
+    }
+}
+
+
void FixPlayermodel()
{
    local string defaultmodel;
@@ -985,12 +1087,22 @@
         for (j = WEP_FIRST; j <= WEP_LAST; ++j)
             weapon_action(j, WR_RESETPLAYER);

+        ///MODIFICATION///
+        self.tts_powerups_invis_fire_recoverfinished = -1;
+        if (tts_spawnshield_mode != 0) {
+            self.tts_spawnshieldfinished = time + tts_spawnshield_time;
+        } else {
+            self.tts_spawnshieldfinished = 0;
+        }
+        self.tts_powerups_invis_nextflicker = -1;
+
        oldself = self;
        self = spot;
            activator = oldself;
                SUB_UseTargets();
            activator = world;
        self = oldself;
+
    } else if(self.classname == "observer") {
        PutObserverInServer ();
    }
@@ -2116,6 +2228,9 @@
                bprint ("^4", self.netname, "^4 is playing now\n");
            if(!cvar("g_campaign"))
                centerprint(self,""); // clear MOTD
+            ///MODIFICATION///
+            OnJoinCheckAndRespawn();
+
            return;
        } else {
            stuffcmd(self,"menu_showteamselect\n");

It is very useful in duel matches Heart
When a player connect match the games starts on 0:0 and spawnfrags dosn.t count ...

okidoki - what you all think about ?

GreetZ Su


RE: TTS mode spawnshield - Mr. Bougo - 11-24-2012

What's TTS?


RE: TTS mode spawnshield - Debugger - 11-24-2012

If the code you posted here is working properly, someone could definitely implement this.

Personally, I dislike the idea of a spawnshield.
Even though it helps the weaker player not to get raped via spawnkills, spawnkilling always was a part of this game. An option could be to implement this but not to enable it by default so the server admin can decide about this.
However, I would rather improve the spawning system itself than work on a spawnshield Wink


RE: TTS mode spawnshield - rafallus - 11-24-2012

Ummm, there already is one, eg. on overkill servers, IIRC it works for 0.5s.


RE: TTS mode spawnshield - hutty - 11-24-2012

[Image: 1Z6n6cRi29M2GGafLxwmEh]

What's TTS?


RE: TTS mode spawnshield - asyyy - 11-24-2012

I agree, the current spawnshield sucks for minstagib. You can't kill the opponent but he kills you - very frustrating at times and it punishes most notably quick aimers. Maybe ask fish if he ports the TTS mod to Xonotic?


RE: TTS mode spawnshield - kojn^ - 11-24-2012

Yes, I dislike the spawn shield also, bloody annoying!


RE: TTS mode spawnshield - Mario - 11-24-2012

Rather than making the spawning player invincible, they could be semi transparent for the spawnshield time.


RE: TTS mode spawnshield - -maniac|Su- - 11-24-2012

The TTS mod was very useful in both Nexuiz Minsta Tournaments in 2009/2010 ..

Here some dokumentation facts by Fish aka <o()))>< :

Code:
========== Documentation of the TTS features =============

History:

TTS started as a small server-side mod for Nexuiz 2.4
specifically tailored to host minstagib tournament matches
(allowing the umpire to modify a player's score, for example).
Since Nexuiz doesn't provide any interface for external mods
or mutators, TTS was implemented by altering the source code
directly.

TTS never grew beyond a small server-side mod. On the contrary,
it shrunk.
When Nexuiz 2.5 was released, I ported TTS to the newer
version (meaning I applied the patch and worked through the
rejects), dropping features that were already present in some
form in the newer Nexuiz version or seemed obsolete or
unpopular to me.

The 2.5.1 release was just a minor step up, but 2.5.2 introduced
some changes to the code which cause the patch from 2.5.1 to
produce a lot of rejects again when applying to Nexuiz 2.5.2
or newer.

Nevertheless, some servers are still running whatever code you
get when you check out upstream Nexuiz from SVN and apply the
TTS patch for 2.5.1, ignoring rejects. This leaves you with
a very small feature set.

This rewrite of TTS starts as a clean(er) re-implementation of these
few features, using Nexuiz SVN revision 8770 as a basis (which will
likely remain the latest revision, as Nexuiz has been discontinued
and is being developed further as the Xonotic fork). Missing
features (or new features) will be (re-)implemented as requested
by the community.





Many, but not all, of the features documented below are only effective
if g_minstagib is set.

FIXME: Document for each feature if it requires g_minstagib.



================ Configuration variables =================

tts_welcomemessage
    type: string
    valid range: any string
    default value: ""
    description:
        If not the empty string, this will be displayed to
        every player when they connect.

tts_welcomemessage_delay
    type: number
    valid range: non-negative real number
    default value: 10
    description:
        Sets the delay for tts_welcomemessage

tts_gamecommencing
    type: flag
    valid range: 0 or 1
    default value: 0
    description:
        Enables or disables automatic score reset on join. If this
        feature is enabled, when a player is playing alone and a
        second player joins, the players' scores are reset and
        the players are respawned.

tts_gamecommencing_delay
    type: number
    valid range: non-negative real
    default value: 3
    description:
        Delay, in seconds, for automatic score reset.

tts_spawnshield_time
    type: number
    valid range: non-negative real
    default value: 2
    description:
        Sets the time, in seconds, for the spawn shield.
        The way spawn shield works is controlled with the
        tts_spawnshield_mode cvar.
        
tts_spawnshield_mode
    type: number
    valid range: 0, 1 or 2
    default value: 1
    description:
        If spawn shield is enabled, players get a grace period
        after spawning during which they can be killed, but
        the attacker doesnt score.
        0: Disable spawn shield feature
        1: Enable spawn shield. If a player fires
        their gun during the spawn shield period,
        they lose the spawn shield immediately, but score the
        frag normally.
        2: Enable spawn shield. If a player wearing spawn shield
        kills another player, they dont score, but the shield
        stays (meaning a player can never score during their own
        spawn shield period).











========================= MUSEUM =========================

Everything from here down is NOT IMPLEMENTED anymore.

Note that you will NOT get any of the functionality by
applying the 2.5.1 TTS patch to 2.5.2 or newer and just
ignoring the rejects.





================ Configuration variables =================

tts_powerups_reuse
    type: flag
    valid range: 0 or 1
    default value: 1
    description:
        Whether or not players drop powerup items when they die.

tts_powerups_invis_claim
    type: number
    valid range: nonnegative real number
    default value: 20
    description:
        Time, in seconds, before a dropped invisibility powerup
        disappears.

tts_powerups_speed_claim
    type: number
    valid range: nonnegative real number
    default value: 20
    description:
        Time, in seconds, before a dropped speed powerup
        disappears.

tts_powerups_invis_cloaktime
    type: number
    valid range: nonnegative real
    default value: 2.0
    description:
        Time, in seconds, it takes a player to cloak and decloak.

tts_logprivatemessages
    type: flag
    valid range: 0 or 1
    default value: 1
    description:
        Whether private messages appear in the server log
        (i.e. they are printed to the server console)
        The messages themselves are censored. Only the sender,
        receiver and message length are logged.

tts_powerups_invis_fire_recovertime
    type: number
    valid range: nonnegative real
    default value: 0
    description:
        Time, in seconds, it takes for a player to recloak
        when they fire a shot while wearing invisibility.

tts_powerups_invis_fire_alpha
    type: number
    valid range: nonnegative real
    default value: 0.1
    description:
        How much to increase alpha level when the player fires a shot.
        This is added to the base alpha level set through
        g_minstagib_invis_alpha


tts_powerups_invis_flicker_average
    type: number
    valid range: real number
    default value: 4.0
    description:
        If nonnegative, specifies the average time between
        invisibility failures (see tts_powerups_invis_flicker_deviation)
        If negative, disables the flicker feature.

tts_powerups_invis_flicker_deviation
    type: number
    valid range: nonnegative real
    default value: 1.5
    description:
        If tts_powerups_invis_flicker_average is nonnegative, invisibility
        will "fail" from time to time, temporarily decloaking the player.
        The time interval between successive failures is a random number
        evenly distributed on the interval
            (_average - _deviation,  _average + _deviation)

tts_powerups_invis_flicker_duration
    type: number
    valid range: nonnegative real
    default value: 0.8
    description:
        The time, in seconds, it takes invisibility to recover from
        a failure.


[removed]    tts_gamecommencing_botsareplayers
[removed]        type: flag
[removed]        valid range: 0 or 1
[removed]        default value: 0
[removed]        description:
[removed]            Whether or not bots count as players for the purpose of the
[removed]            tts_gamecommencing facility. This is a case where i promoted
[removed]            a bug to a feature. Set to 1 to restore the old ("buggy")
[removed]            behavior.


Removed these because i was too lazy to adapt them to 2.5.1. They're not really
important anyway. I might reintroduce them when someone asks.
[removed]    tts_emptyservernomapchange
[removed]        type: flag
[removed]        valid range: 0 or 1
[removed]        default value: 0
[removed]        description:
[removed]            If this flag is set, the server refrains from changing the
[removed]            map when it is empty.
[removed]            When the time limit for the current map expires and the
[removed]            server is empty, the match time is extended by whatever
[removed]            the initial time limit was, provided no player has connected
[removed]            since the map has been on, and the maximum time limit set through
[removed]            tts_emptyservernomapchange_maxtime has not yet been exceeded.

[removed]    tts_emptyservernomapchange_maxtime
[removed]        type: number
[removed]        valid range: real number
[removed]        default value: -1
[removed]        description:
[removed]            Sets the maximum time limit for mapchange prevention (see
[removed]            tts_emptyservernomapchange)
[removed]            Nonnegative values are interpreted as the maximum time limit,
[removed]            in minutes. Negative values are interpreted as infinity, thus
[removed]            allowing postponing the mapchange forever.


Nexuiz 2.5.1 now has the sv_vote_master_commands cvar, which fulfills the exact same
purpose as tts_vote_mastercommands.
[removed]    tts_vote_mastercommands
[removed]        type: string
[removed]        valid range: any string
[removed]        default value: ""
[removed]        description:
[removed]            A list of commands (just like sv_vote_commands) which can
[removed]            only be executed by masters (using vdo), but cannot be issued
[removed]            in a vcall.

tts_laser_jumpinterval
    type: number
    valid range: positive real number
    default value: 0.9
    description:
        Refire time, in seconds, for the laser in minstagib.
        This is hard-coded as 0.9 in vanilla Nexuiz.


tts_master_kickimmunity
    type: flag
    valid range: 0 or 1
    default value: 0
    description:
        Whether or not, players logged in as masters are immune to
        kicks and kickbans issued through vcall. This is only effective
        if the player is already logged in as master at the time
        the vote is called.
        NEW: Also affects kicks issued through vdo, i.e. masters cannot
        kick one another anymore. So disable this if you allow votes
        to become master.

Maybe reintroduce this or something similar at a later time.
[removed]    tts_master_referee
[removed]        type: flag
[removed]        valid range: 0 or 1
[removed]        default value: 0
[removed]        description:
[removed]            Whether masters are considered "referees". This causes the
[removed]            word "referee" to be displayed instead of "master" when a
[removed]            master logs in or issues commands, but has no other effect.


tts_lockedgame_init
    type: flag
    valid range: 0 or 1
    default value: 0
    description:
        Whether the game is initially "locked" after each mapchange.
        See the lockgame server command for more info.


tts_noautomapchange
    type: flag
    valid range: 0 or 1
    default value: 0
    description:
        If this flag is set, the map is not changed after a match has
        ended. It has to be changed manually using gotomap each time.


A similar cvar now exists in Nexuiz 2.5.1, g_chat_nospectators. The semantics of
vanilla g_chat_nospectators has been altered, in that it is rendered ineffective
when the game ends.
[removed]    tts_specchat_restricted
[removed]        type: flag
[removed]        valid range: 0 or 1
[removed]        default value: 0
[removed]        description:
[removed]            If this flag is set, players do not see chat messages from spectators
[removed]            until the match is over.


The functionality of tts_maxactiveplayers is now provided by g_maxplayers.
[removed]    tts_maxactiveplayers
[removed]        type: number
[removed]        valid range: integer
[removed]        default value: -1
[removed]        description:
[removed]            Specifies the maximum number of players that can play
[removed]            simultaneously. Negative values are interpreted as infinity.
        
tts_printplayerstats
    type: number
    valid range: 0, 1 or 2
    default value: 0
    description:
        When the match ends, player statistics can be printed into
        the main chat. This variable controls how.
        0: No stats are printed.
        1: Each player only sees their own stats.
        2: All stats are printed.

tts_defaultpowerupmode
    type: string
    valid range:  "off", "on", "map", "ammo" or "noammo"
    default value: "on"
    description:
        Sets the initial powerup mode. The powerup mode can be changed on the fly
        using the powerupmode server command. See there.
    
tts_powerups_likelihood_invis
tts_powerups_likelihood_speed
tts_powerups_likelihood_lives
    type: number
    valid range: positive real number
    default value: 1
    description:
        Each of these variables controls the probability of a powerup being
        invisibility, speed or extra lives, respectively.
        The sum does not have to be 1. The actual likelihood for a specific
        type of powerup is the value of its controlling variable, divided by
        the total.


============== Server commands ================

freezegame SWITCH
    Freezes (if SWITCH is "on") or unfreezes the game (if SWITCH is "off").
    While the game is frozen, players cannot move or shoot.

forcespec # NUM_1 ... NUM_N
    Forces N players into spectator mode simultaneously.
    NUM_1 through NUM_N are player numbers according to status.
    The space after the pound sign (#) is mandatory.

forcejoin # NUM_1 ... NUM_N
    Forces N spectators into the game simultaneously.
    NUM_1 through NUM_N are player numbers according to status.
    The space after the pound sign (#) is mandatory.


lockgame SWITCH
    Locks or unlocks the game according to SWITCH (which can be
    "on" or "off").
    While the game is locked, players cannot leave the game and
    spectators cannot join.
    The initial state of the lock can be set with the
    tts_lockedgame_init cvar.

awardfrags # PLNUM FRAGS
    Adjusts a player's score.
    PLNUM is the client number of a player according to status.
    FRAGS is an integer that is added to the player's current
    score.

powerupmode MODE
    Changes the powerup mode in a minstagib game.
    Possible values for MODE are:
    "off": Removes all powerup items (invis, speed, lives) from the map.
    "on": Randomly spawns invis, speed or lives in the powerup locations.
        This the normal behavior of Nexuiz.
    "map": The type of powerups is determined by the map. More to the point,
        this spawns the respective MinstaGib items of normal powerups,
        i.e. mega health becomes extra lives, strength becomes invisibility,
        and invincibility becomes speed.
    "ammo": Replaces powerups with ammunition.
    "noammo": Removes all powerup items AND ammunition from the map.
    NOTE: You cannot execute this command in your server.cfg in order to
    set the initial powerup mode. The initial mode is controlled by the
    tts_defaultpowerupmode variable.

removepowerups
    This is an alias for powerupmode off

addpowerups
    This is an alias for powerupmode on

assassinate # PLNUM
    Assassinates the player with number PLNUM, according to status.
    The player is killed and loses a frag, just like if they committed
    suicide.

awarditem # PLNUM ITEM
    Gives an item to the player with number PLNUM, according to status.
    ITEM can be one of "ammo", "invis", "speed" and "lives".

============== Client commands ================

cmd mastermsg MESSAGE
    Sends a master message, MESSAGE, to the chat. The message
    is visible to all players connected to the server, regardless
    of chat restrictions.
    A player must be logged in as master to use this command.

[removed]    cmd force_reset_view
[removed]        Resets the player's camera.

Found here the orginal code:
Code:
Index: data/qcsrc/server/g_damage.qc
===================================================================
--- data/qcsrc/server/g_damage.qc    (revision 8003)
+++ data/qcsrc/server/g_damage.qc    (working copy)
@@ -370,12 +370,38 @@
                    }
                }

+                ///MODIFICATION///
+                local float fragsup, spawnfrag;
+                fragsup = 1;
+                spawnfrag = FALSE;
+                if (tts_spawnshield_mode != 0)
+                    if(time < targ.tts_spawnshieldfinished || (tts_spawnshield_mode == 2 && time < attacker.tts_spawnshieldfinished)) {    
+                        fragsup = 0;
+                        spawnfrag = TRUE;
+                    }
+                if (targ.classname=="corpse")
+                    fragsup = 0;
+
+                local string typefragremark;
+                local string spawnfragremark;
+                
+                if (targ.buttonchat) typefragremark = "^7type";
+                else typefragremark = "";
+                if (spawnfrag) spawnfragremark = "^2spawn";
+                else spawnfragremark = "";
+
+
                if(sv_gentle > 0) {
-                    centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, "^4You scored against ^7", s));
+                    centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, blood_message, "^4You scored against ^7", s));
                    centerprint(targ, strcat(DAMAGE_CENTERPRINT_SPACER, a,"^1 scored against you ^7"));
                } else {
-                    centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, blood_message, "^4You fragged ^7", s));
-                    centerprint(targ, strcat(DAMAGE_CENTERPRINT_SPACER, victim_message, "^1You were fragged by ^7", a));
+                    if((cvar("sv_fragmessage_information_typefrag")) && (targ.BUTTON_CHAT)) {
+                        centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, blood_message, "^4You ^1typefragged ^7", s));
+                        centerprint(targ, strcat(DAMAGE_CENTERPRINT_SPACER, victim_message, "^1You were typefragged by ^7", a));
+                    } else {
+                        centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, blood_message, "^4You ",spawnfragremark, typefragremark,"^4fragged ^7", s));
+                                                centerprint(targ, strcat(DAMAGE_CENTERPRINT_SPACER, victim_message, "^1You were ",spawnfragremark, typefragremark, "^1fragged by ^7", a));
+                    }
                    attacker.taunt_soundtime = time + 1;
                }

@@ -435,7 +461,7 @@
                    GiveFrags(attacker, targ, 0); // for logging
                }
                else
-                    GiveFrags(attacker, targ, 1);
+                    GiveFrags(attacker, targ, fragsup);

                if (targ.killcount > 2) {
                    if(sv_gentle)
@@ -713,6 +739,12 @@
                self = oldself;
                return;
            }
+
+            ///MODIFICATION///
+            if ((deathtype == WEP_MINSTANEX) && damage) {
+                attacker.tts_hits ++;
+            }
+
            if (targ.armorvalue && (deathtype == WEP_MINSTANEX) && damage)
            {
                targ.armorvalue -= 1;
Index: data/qcsrc/server/defs.qh
===================================================================
--- data/qcsrc/server/defs.qh    (revision 8003)
+++ data/qcsrc/server/defs.qh    (working copy)
@@ -623,3 +623,15 @@

.entity clientdata;
.entity personal;
+
+
+///MODIFICATION///
+.float tts_powerups_invis_fire_recoverfinished;
+.float tts_powerups_invis_fire_recoverduration;
+.float tts_powerups_invis_started;
+.float tts_spawnshieldfinished;
+.float tts_powerups_invis_nextflicker;
+.float tts_hits;
+.float tts_shotsfired;
+float tts_lockedgame;
+float tts_gamefrozen;
Index: data/qcsrc/server/w_minstanex.qc
===================================================================
--- data/qcsrc/server/w_minstanex.qc    (revision 8003)
+++ data/qcsrc/server/w_minstanex.qc    (working copy)
@@ -179,10 +179,27 @@
    {
        if (self.BUTTON_ATCK)
        {
-            if (weapon_prepareattack(0, cvar("g_balance_minstanex_refire")))
+            ///MODIFICATION///
+            local float refire_factor;
+            refire_factor = 1.0;
+            
+            local float actual_refire;
+            actual_refire = cvar("g_balance_minstanex_refire") * refire_factor;
+
+            if (tts_spawnshield_mode == 1 && time < self.tts_spawnshieldfinished)
+                self.tts_spawnshieldfinished = time;
+
+            if (weapon_prepareattack(0, actual_refire))
            {
                W_MinstaNex_Attack();
                weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_minstanex_animtime"), w_ready);
+                ///MODIFICATION///
+                if(g_minstagib && (self.items & IT_STRENGTH) && tts_powerups_invis_fire_recovertime>0) {
+                    self.tts_powerups_invis_fire_recoverfinished =
+                        time + tts_powerups_invis_fire_recovertime;
+                    self.tts_powerups_invis_fire_recoverduration = tts_powerups_invis_fire_recovertime;
+                }                
+                self.tts_shotsfired ++;
            }
        }
        else if (self.BUTTON_ATCK2)
Index: data/qcsrc/server/miscfunctions.qc
===================================================================
--- data/qcsrc/server/miscfunctions.qc    (revision 8003)
+++ data/qcsrc/server/miscfunctions.qc    (working copy)
@@ -1042,6 +1042,30 @@
float sv_autotaunt;
float sv_taunt;

+
+
+///MODIFICATION///
+// Not all tts_ cvars have a declarator here, but most do.
+// Some are read on the fly, especially the welcomemessage ones
+float tts_powerups_reuse;
+float tts_powerups_invis_claim;
+float tts_powerups_speed_claim;
+
+float tts_powerups_invis_cloaktime;
+float tts_powerups_invis_fire_recovertime;
+float tts_powerups_invis_fire_alpha;
+float tts_powerups_invis_flicker_average;
+float tts_powerups_invis_flicker_deviation;
+float tts_powerups_invis_flicker_duration;
+
+float tts_spawnshield_time;
+float tts_spawnshield_mode;
+
+float tts_laser_jumpinterval;
+
+
+
+
void readlevelcvars(void)
{
     g_bugrigs = cvar("g_bugrigs");
@@ -1168,6 +1192,24 @@
     if not(inWarmupStage)
         game_starttime                 = cvar("g_start_delay");

+
+    ///MODIFICATION///
+    tts_powerups_reuse = cvar("tts_powerups_reuse");
+    tts_powerups_invis_claim = cvar("tts_powerups_invis_claim");
+    tts_powerups_speed_claim = cvar("tts_powerups_speed_claim");
+    
+    tts_powerups_invis_cloaktime = cvar("tts_powerups_invis_cloaktime");
+    tts_powerups_invis_fire_recovertime = cvar("tts_powerups_invis_fire_recovertime");
+    tts_powerups_invis_fire_alpha = cvar("tts_powerups_invis_fire_alpha");
+    tts_powerups_invis_flicker_average = cvar("tts_powerups_invis_flicker_average");
+    tts_powerups_invis_flicker_deviation = cvar("tts_powerups_invis_flicker_deviation");
+    tts_powerups_invis_flicker_duration = cvar("tts_powerups_invis_flicker_duration");
+            
+    tts_spawnshield_time = cvar("tts_spawnshield_time");
+    tts_spawnshield_mode = cvar("tts_spawnshield_mode");
+    
+    tts_laser_jumpinterval = cvar("tts_laser_jumpinterval");
+
     readplayerstartcvars();
}

Index: data/qcsrc/server/cl_client.qc
===================================================================
--- data/qcsrc/server/cl_client.qc    (revision 8003)
+++ data/qcsrc/server/cl_client.qc    (working copy)
@@ -660,6 +660,10 @@
    }
    else
        self.frags = FRAGS_SPECTATOR;
+
+    ///MODIFICATION///
+    self.tts_hits = 0;
+    self.tts_shotsfired = 0;
}

float RestrictSkin(float s)
@@ -671,6 +675,104 @@
    return mod(s, 3);
}

+
+
+///MODIFICATION///
+
+float CountActivePlayers() {
+    local entity pl;
+    local float plcnt;
+    local float countbots;
+    if(cvar("tts_gamecommencing_botsareplayers")) {
+        FOR_EACH_PLAYER(pl) plcnt+=1;
+    } else {
+        FOR_EACH_REALPLAYER(pl) plcnt+=1;
+    }
+    return plcnt;
+}
+
+void GameCommencing_Think() {
+    local float plcnt;
+    local entity pl;
+    local entity oldself;
+    
+    // Count number of players again, as they may have
+    // changed since the entity was created.
+    plcnt = CountActivePlayers();
+    
+    //bprint("^1DEBUG: ^3GameCommencing entity think\n");
+    
+    if(plcnt >= 2) {
+        // Output an info message in the console
+        print("^3Second player joined, starting game.\n");
+        
+        // Respawn each player and reset their score
+        FOR_EACH_PLAYER(pl) {
+            oldself = self;
+            self = pl;
+            if(self.flagcarried)
+                DropFlag(self.flagcarried, world, world);
+            self.frags = 0;
+            //self.deaths = 0;
+            self.killcount = 0;
+            //self.tts_kills = 0;
+            //self.tts_suicides = 0;
+            self.tts_hits = 0;
+            self.tts_shotsfired = 0;
+            PlayerScore_Clear(self);
+            PutClientInServer();
+            self = oldself;
+        }
+        
+        // Respawn all items
+        local entity it;
+        for(it=find(world,classname,"minstagib");it!=world;it=find(it,classname,"minstagib")) {
+            // NOTE: Checking for think is paramount! If think is not set,
+            // but nextthink is changed, the server ABORTS!
+            if(it.think)
+                it.nextthink = time;
+        }
+        
+        // Remove dropped weapons
+        for(it=find(world,classname,"droppedweapon");it!=world;it=find(it,classname,"droppedweapon")) {
+            it.think = RemoveItem;
+            it.nextthink = time;
+        }
+    }
+    
+    // Were no longer needed.
+    remove(self);
+}
+
+// Well, I tried to be as descriptive as possible in the function's name
+// It's supposed to be called on player join. If it counts 2 active players,
+// it respawns all players. (Counter-Strike style "Game Commencing")
+void OnJoinCheckAndRespawn() {
+    if(!cvar("tts_gamecommencing") || !g_minstagib) return;
+    
+    local float plcnt;
+    
+    // Count active players
+    plcnt = CountActivePlayers();
+    
+    //bprint(strcat("^1DEBUG: ^3Player count now ",ftos(plcnt),"\n"));
+    
+    if(plcnt==2) {
+        bcenterprint("^3Game commencing...\n");
+        local entity gamecommencing;
+        
+        // Do not spawn game-commencing entity if one already exists
+        if( (gamecommencing=find(world,classname,"gamecommencing_entity")) == world )
+            gamecommencing = spawn();
+        
+        gamecommencing.owner = world;
+        gamecommencing.classname = "gamecommencing_entity";
+        gamecommencing.think = GameCommencing_Think;
+        gamecommencing.nextthink = time + cvar("tts_gamecommencing_delay");
+    }
+}
+
+
void FixPlayermodel()
{
    local string defaultmodel;
@@ -985,12 +1087,22 @@
         for (j = WEP_FIRST; j <= WEP_LAST; ++j)
             weapon_action(j, WR_RESETPLAYER);

+        ///MODIFICATION///
+        self.tts_powerups_invis_fire_recoverfinished = -1;
+        if (tts_spawnshield_mode != 0) {
+            self.tts_spawnshieldfinished = time + tts_spawnshield_time;
+        } else {
+            self.tts_spawnshieldfinished = 0;
+        }
+        self.tts_powerups_invis_nextflicker = -1;
+
        oldself = self;
        self = spot;
            activator = oldself;
                SUB_UseTargets();
            activator = world;
        self = oldself;
+
    } else if(self.classname == "observer") {
        PutObserverInServer ();
    }
@@ -2116,6 +2228,9 @@
                bprint ("^4", self.netname, "^4 is playing now\n");
            if(!cvar("g_campaign"))
                centerprint(self,""); // clear MOTD
+            ///MODIFICATION///
+            OnJoinCheckAndRespawn();
+
            return;
        } else {
            stuffcmd(self,"menu_showteamselect\n");

Maybe a dev should take a look at this ...
Without this mode minsta tournaments even not conceivably ...

GreetZ Su


RE: TTS mode spawnshield - Mr. Bougo - 11-25-2012

Note that Xonotic has a mutator API of some sort now, so the best way to port this would be to restructure it using that.