]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/gamemode_keepaway.qc
Improvements to Keepaway (move scorerules to ka file, split declarations)
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_keepaway.qc
index 85e77fe771fcd8880fd97297617d6533faeb4b1f..25a41f13d213795abe3b0586d45f8f4a25854084 100644 (file)
@@ -1,60 +1,23 @@
-void ka_SpawnBall(void);
-void ka_TouchEvent(void);
-void ka_RespawnBall(void);
-void ka_DropEvent(entity);
-void ka_TimeScoring(void);
+// ===========================================================
+//  Keepaway game mode coding, written by Samual and Diabolik
+//  Last updated: September, 2012
+// ===========================================================
 
-entity ka_ball;
-
-float ka_ballcarrier_waypointsprite_visible_for_player(entity);
-
-void ka_Initialize() // run at the start of a match, initiates game mode
+float ka_ballcarrier_waypointsprite_visible_for_player(entity e) // runs on waypoints which are attached to ballcarriers, updates once per frame 
 {
-       if(!g_keepaway)
-               return;
+       if(e.ballcarried)
+               if(other.classname == "spectator") 
+                       return FALSE; // we don't want spectators of the ballcarrier to see the attached waypoint on the top of their screen
                
-       precache_sound("keepaway/pickedup.wav");
-       precache_sound("keepaway/dropped.wav");
-       precache_sound("keepaway/respawn.wav");
-       precache_sound("keepaway/touch.wav");
-
-       ScoreRules_keepaway();
-       ka_SpawnBall();
-}
-
-void ka_Reset() // used to clear the ballcarrier whenever the match switches from warmup to normal
-{
-       if(self.owner)
-               if(self.owner.classname == "player")
-                       ka_DropEvent(self.owner);
+       // TODO: Make the ballcarrier lack a waypointsprite whenever they have the invisibility powerup
 
-       ka_RespawnBall();
+       return TRUE;
 }
 
-void ka_SpawnBall() // loads various values for the ball, runs only once at start of match
+void ka_EventLog(string mode, entity actor) // use an alias for easy changing and quick editing later
 {
-       if(!g_keepaway) { return; }
-       
-       entity e;
-       e = spawn();
-       e.model = "models/orbs/orbblue.md3";    
-       precache_model(e.model);
-       setmodel(e, e.model);
-       setsize(e, '-16 -16 -20', '16 16 20'); // 20 20 20 was too big, player is only 16 16 24... gotta cheat with the Z (20) axis so that the particle isn't cut off
-       e.classname = "keepawayball";
-       e.damageforcescale = autocvar_g_keepawayball_damageforcescale;
-       e.takedamage = DAMAGE_YES;
-       e.solid = SOLID_TRIGGER;
-       e.movetype = MOVETYPE_BOUNCE;
-       e.glow_color = autocvar_g_keepawayball_trail_color;
-       e.glow_trail = TRUE;
-       e.flags = FL_ITEM;
-       e.reset = ka_Reset;
-       e.touch = ka_TouchEvent;
-       e.owner = world;
-       ka_ball = e;
-
-       InitializeEntity(e, ka_RespawnBall, INITPRIO_SETLOCATION); // is this the right priority? Neh, I have no idea.. Well-- it works! So. 
+       if(autocvar_sv_eventlog)
+               GameLogEcho(strcat(":ka:", mode, ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
 }
 
 void ka_RespawnBall() // runs whenever the ball needs to be relocated
@@ -78,7 +41,7 @@ void ka_RespawnBall() // runs whenever the ball needs to be relocated
                WaypointSprite_Spawn("ka-ball", 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAGCARRIER, '0 1 1');
                WaypointSprite_Ping(self.waypointsprite_attachedforcarrier);    
 
-               sound(self, CH_TRIGGER_SINGLE, "keepaway/respawn.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) 
+               sound(self, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) 
        }
        else
        {
@@ -86,6 +49,18 @@ void ka_RespawnBall() // runs whenever the ball needs to be relocated
        }
 }
 
+void ka_TimeScoring()
+{
+       if(self.owner.ballcarried)
+       { // add points for holding the ball after a certain amount of time
+               if(autocvar_g_keepaway_score_timepoints)
+                       PlayerScore_Add(self.owner, SP_SCORE, autocvar_g_keepaway_score_timepoints);
+                       
+               PlayerScore_Add(self.owner, SP_KEEPAWAY_BCTIME, (autocvar_g_keepaway_score_timeinterval / 1)); // interval is divided by 1 so that time always shows "seconds"
+               self.nextthink = time + autocvar_g_keepaway_score_timeinterval;
+       }
+}
+
 void ka_TouchEvent() // runs any time that the ball comes in contact with something
 {
        if(gameover) { return; }
@@ -99,7 +74,7 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth
        if(other.classname != "player") 
        {  // The ball just touched an object, most likely the world
                pointparticles(particleeffectnum("kaball_sparks"), self.origin, '0 0 0', 1);
-               sound(self, CH_TRIGGER_SINGLE, "keepaway/touch.wav", VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER, "keepaway/touch.wav", VOL_BASE, ATTN_NORM);
                return; 
        }
        else if(self.wait > time) { return; }
@@ -125,6 +100,7 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth
        other.effects |= autocvar_g_keepaway_ballcarrier_effects;
        
        // messages and sounds
+       ka_EventLog("pickup", other);
        Send_KillNotification(other.netname, "", "", KA_PICKUPBALL, MSG_KA);
        WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
        WriteString(MSG_BROADCAST, strcat(other.netname, "^7 has picked up the ball!"));
@@ -167,15 +143,11 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los
        plyr.effects &~= autocvar_g_keepaway_ballcarrier_effects;
 
        // messages and sounds
+       ka_EventLog("dropped", plyr);
        Send_KillNotification(plyr.netname, "", "", KA_DROPBALL, MSG_KA);
        WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
-<<<<<<< HEAD
-       WriteString(MSG_BROADCAST, strcat("\n\n", plyr.netname, "^7 has dropped the ball!\n"));
-       sound(plyr, CH_TRIGGER, "keepaway/dropped.wav", VOL_BASE, ATTN_NONE);   // ATTN_NONE (it's a sound intended to be heard anywhere) 
-=======
        WriteString(MSG_BROADCAST, strcat(plyr.netname, "^7 has dropped the ball!"));
-       sound(other, CHAN_AUTO, "keepaway/dropped.wav", VOL_BASE, ATTN_NONE);   // ATTN_NONE (it's a sound intended to be heard anywhere) 
->>>>>>> terencehill/centerprint_stuff
+       sound(other, CH_TRIGGER, "keepaway/dropped.wav", VOL_BASE, ATTN_NONE);  // ATTN_NONE (it's a sound intended to be heard anywhere) 
        
        // scoring
        // PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1); Not anymore, this is 100% the same as pickups and is useless.
@@ -187,28 +159,18 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los
        WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier);
 }
 
-float ka_ballcarrier_waypointsprite_visible_for_player(entity e) // runs on waypoints which are attached to ballcarriers, updates once per frame 
+void ka_Reset() // used to clear the ballcarrier whenever the match switches from warmup to normal
 {
-       if(e.ballcarried)
-               if(other.classname == "spectator") 
-                       return FALSE; // we don't want spectators of the ballcarrier to see the attached waypoint on the top of their screen
-               
-       // TODO: Make the ballcarrier lack a waypointsprite whenever they have the invisibility powerup
+       if((self.owner) && (self.owner.classname == "player"))
+               ka_DropEvent(self.owner);
 
-       return TRUE;
+       ka_RespawnBall();
 }
 
-void ka_TimeScoring()
-{
-       if(self.owner.ballcarried)
-       { // add points for holding the ball after a certain amount of time
-               if(autocvar_g_keepaway_score_timepoints)
-                       PlayerScore_Add(self.owner, SP_SCORE, autocvar_g_keepaway_score_timepoints);
-                       
-               PlayerScore_Add(self.owner, SP_KEEPAWAY_BCTIME, (autocvar_g_keepaway_score_timeinterval / 1)); // interval is divided by 1 so that time always shows "seconds"
-               self.nextthink = time + autocvar_g_keepaway_score_timeinterval;
-       }
-}
+
+// ==============
+// Hook Functions
+// ==============
 
 MUTATOR_HOOKFUNCTION(ka_Scoring)
 {
@@ -310,6 +272,61 @@ MUTATOR_HOOKFUNCTION(ka_PlayerPowerups)
        return 0;
 }
 
+
+// ==============
+// Initialization
+// ==============
+
+void ka_SpawnBall() // loads various values for the ball, runs only once at start of match
+{
+       if(!g_keepaway) { return; }
+       
+       entity e;
+       e = spawn();
+       e.model = "models/orbs/orbblue.md3";    
+       precache_model(e.model);
+       setmodel(e, e.model);
+       setsize(e, '-16 -16 -20', '16 16 20'); // 20 20 20 was too big, player is only 16 16 24... gotta cheat with the Z (20) axis so that the particle isn't cut off
+       e.classname = "keepawayball";
+       e.damageforcescale = autocvar_g_keepawayball_damageforcescale;
+       e.takedamage = DAMAGE_YES;
+       e.solid = SOLID_TRIGGER;
+       e.movetype = MOVETYPE_BOUNCE;
+       e.glow_color = autocvar_g_keepawayball_trail_color;
+       e.glow_trail = TRUE;
+       e.flags = FL_ITEM;
+       e.reset = ka_Reset;
+       e.touch = ka_TouchEvent;
+       e.owner = world;
+       ka_ball = e;
+
+       InitializeEntity(e, ka_RespawnBall, INITPRIO_SETLOCATION); // is this the right priority? Neh, I have no idea.. Well-- it works! So. 
+}
+
+void ka_ScoreRules()
+{
+       ScoreRules_basics(0, SFL_SORT_PRIO_PRIMARY, 0, TRUE); // SFL_SORT_PRIO_PRIMARY
+       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_PICKUPS,                     "pickups",              0);
+       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_CARRIERKILLS,        "bckills",              0);
+       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_BCTIME,                      "bctime",               SFL_SORT_PRIO_SECONDARY);
+       ScoreRules_basics_end();
+}
+
+void ka_Initialize() // run at the start of a match, initiates game mode
+{
+       if(!g_keepaway)
+               return;
+               
+       precache_sound("keepaway/pickedup.wav");
+       precache_sound("keepaway/dropped.wav");
+       precache_sound("keepaway/respawn.wav");
+       precache_sound("keepaway/touch.wav");
+
+       ka_ScoreRules();
+       ka_SpawnBall();
+}
+
+
 MUTATOR_DEFINITION(gamemode_keepaway)
 {
        MUTATOR_HOOK(MakePlayerObserver, ka_RemovePlayer, CBC_ORDER_ANY);
@@ -325,13 +342,11 @@ MUTATOR_DEFINITION(gamemode_keepaway)
        {
                if(time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
-               g_keepaway = 1;
                ka_Initialize();
        }
 
        MUTATOR_ONREMOVE
        {
-               g_keepaway = 0;
                error("This is a game type and it cannot be removed at runtime.");
        }