]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/gamemode_nexball.qc
Merge branch 'master' into Mario/weapons
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_nexball.qc
index 5831250d2d4b29cf144821413fc4028d7239483f..176fb1eac5e9fcee4270c01fdc705dd25e28d3f8 100644 (file)
@@ -107,7 +107,7 @@ void GiveBall(entity plyr, entity ball)
        {
                WaypointSprite_Kill(ball.waypointsprite_attachedforcarrier);
        }
-       
+
        //setattachment(ball, plyr, "");
        setorigin(ball, plyr.origin + plyr.view_ofs);
 
@@ -136,13 +136,13 @@ void GiveBall(entity plyr, entity ball)
                ball.think = DropOwner;
                ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold;
        }
-       
+
        ownr = self;
-       self = plyr;    
+       self = plyr;
        self.weaponentity.weapons = self.weapons;
        self.weaponentity.switchweapon = self.weapon;
        self.weapons = WEPSET_PORTO;
-       weapon_action(WEP_PORTO, WR_RESETPLAYER);
+       WEP_ACTION(WEP_PORTO, WR_RESETPLAYER);
        self.switchweapon = WEP_PORTO;
        W_SwitchWeapon(WEP_PORTO);
        self = ownr;
@@ -248,7 +248,7 @@ void football_touch(void)
                        self.nextthink = time + autocvar_g_nexball_delay_idle;
                return;
        }
-       if not(IS_PLAYER(other))
+       if (!IS_PLAYER(other))
                return;
        if(other.health < 1)
                return;
@@ -457,11 +457,21 @@ void nb_spawnteams(void)
        }
 }
 
+// scoreboard setup
+void nb_ScoreRules(float teams)
+{
+       ScoreRules_basics(teams, 0, 0, TRUE);
+       ScoreInfo_SetLabel_TeamScore(   ST_NEXBALL_GOALS,  "goals", SFL_SORT_PRIO_PRIMARY);
+       ScoreInfo_SetLabel_PlayerScore( SP_NEXBALL_GOALS,  "goals", SFL_SORT_PRIO_PRIMARY);
+       ScoreInfo_SetLabel_PlayerScore(SP_NEXBALL_FAULTS, "faults", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER);
+       ScoreRules_basics_end();
+}
+
 void nb_delayedinit(void)
 {
        if(find(world, classname, "nexball_team") == world)
                nb_spawnteams();
-       ScoreRules_nexball(nb_teams);
+       nb_ScoreRules(nb_teams);
 }
 
 
@@ -471,11 +481,7 @@ void nb_delayedinit(void)
 
 void SpawnBall(void)
 {
-       if(!g_nexball)
-       {
-               remove(self);
-               return;
-       }
+       if(!g_nexball) { remove(self); return; }
 
 //     balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
 
@@ -529,7 +535,7 @@ void spawnfunc_nexball_basketball(void)
 {
        nexball_mode |= NBM_BASKETBALL;
        self.classname = "nexball_basketball";
-       if not(balls & BALL_BASKET)
+       if (!(balls & BALL_BASKET))
        {
                /*
                CVTOV(g_nexball_basketball_effects_default);
@@ -559,14 +565,28 @@ void spawnfunc_nexball_football(void)
        SpawnBall();
 }
 
+float nb_Goal_Customize()
+{
+       entity e, wp_owner;
+       e = WaypointSprite_getviewentity(other);
+       wp_owner = self.owner;
+       if(SAME_TEAM(e, wp_owner)) { return FALSE; }
+
+       return TRUE;
+}
+
 void SpawnGoal(void)
 {
-       if(!g_nexball)
+       if(!g_nexball) { remove(self); return; }
+
+       EXACTTRIGGER_INIT;
+
+       if(self.team != GOAL_OUT && Team_TeamToNumber(self.team) != -1)
        {
-               remove(self);
-               return;
+               WaypointSprite_SpawnFixed("goal", (self.absmin + self.absmax) * 0.5, self, sprite, RADARICON_NONE, ((self.team) ? Team_ColorRGB(self.team) : '1 0.5 0'));
+               self.sprite.customizeentityforclient = nb_Goal_Customize;
        }
-       EXACTTRIGGER_INIT;
+
        self.classname = "nexball_goal";
        if(self.noise == "")
                self.noise = "ctf/respawn.wav";
@@ -655,13 +675,13 @@ void W_Nexball_Think()
        //dprint("W_Nexball_Think\n");
        //vector new_dir = steerlib_arrive(self.enemy.origin, 2500);
        vector new_dir = normalize(self.enemy.origin + '0 0 50' - self.origin);
-       vector old_dir = normalize(self.velocity);       
-       float _speed = vlen(self.velocity);     
+       vector old_dir = normalize(self.velocity);
+       float _speed = vlen(self.velocity);
        vector new_vel = normalize(old_dir + (new_dir * autocvar_g_nexball_safepass_turnrate)) * _speed;
        //vector new_vel = (new_dir * autocvar_g_nexball_safepass_turnrate
-       
+
        self.velocity = new_vel;
-       
+
        self.nextthink = time;
 }
 
@@ -671,10 +691,10 @@ void W_Nexball_Touch(void)
        attacker = self.owner;
        //self.think = func_null;
        //self.enemy = world;
-       
+
        PROJECTILE_TOUCH;
        if(attacker.team != other.team || autocvar_g_nexball_basketball_teamsteal)
-               if((ball = other.ballcarried) && (IS_PLAYER(attacker)))
+               if((ball = other.ballcarried) && !other.deadflag && (IS_PLAYER(attacker)))
                {
                        other.velocity = other.velocity + normalize(self.velocity) * other.damageforcescale * autocvar_g_balance_nexball_secondary_force;
                        other.flags &= ~FL_ONGROUND;
@@ -683,7 +703,7 @@ void W_Nexball_Touch(void)
                                LogNB("stole", attacker);
                                sound(other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTEN_NORM);
 
-                               if(attacker.team == other.team && time > attacker.teamkill_complain)
+                               if(SAME_TEAM(attacker, other) && time > attacker.teamkill_complain)
                                {
                                        attacker.teamkill_complain = time + 5;
                                        attacker.teamkill_soundtime = time + 0.4;
@@ -725,9 +745,9 @@ void W_Nexball_Attack(float t)
                        mul = 2 - mul;
                mul = mi + (ma - mi) * mul; // range from the minimal power to the maximal power
        }
-       
+
        DropBall(ball, w_shotorg, W_CalculateProjectileVelocity(self.velocity, w_shotdir * autocvar_g_balance_nexball_primary_speed * mul, FALSE));
-       
+
 
        //TODO: use the speed_up cvar too ??
 }
@@ -743,10 +763,10 @@ void W_Nexball_Attack2(void)
                _ball.nextthink = time;
                return;
        }
-       
+
        if(!autocvar_g_nexball_tackling)
                return;
-       
+
        entity missile;
        if(!(balls & BALL_BASKET))
                return;
@@ -760,11 +780,11 @@ void W_Nexball_Attack2(void)
        missile.movetype = MOVETYPE_FLY;
        PROJECTILE_MAKETRIGGER(missile);
 
-       setmodel(missile, "models/elaser.mdl");  // precision set below
+       //setmodel(missile, "models/elaser.mdl");  // precision set below
        setsize(missile, '0 0 0', '0 0 0');
        setorigin(missile, w_shotorg);
 
-       W_SetupProjectileVelocity(missile, autocvar_g_balance_nexball_secondary_speed, 0);
+       W_SetupProjVelocity_Basic(missile, autocvar_g_balance_nexball_secondary_speed, 0);
        missile.angles = vectoangles(missile.velocity);
        missile.touch = W_Nexball_Touch;
        missile.think = SUB_Remove;
@@ -772,6 +792,8 @@ void W_Nexball_Attack2(void)
 
        missile.effects = EF_BRIGHTFIELD | EF_LOWPRECISION;
        missile.flags = FL_PROJECTILE;
+
+       CSQCProjectile(missile, TRUE, PROJECTILE_ELECTRO, TRUE);
 }
 
 float ball_customize()
@@ -782,8 +804,8 @@ float ball_customize()
                self.scale = 1;
                self.customizeentityforclient = func_null;
                return TRUE;
-       }               
-       
+       }
+
        if(other == self.owner)
        {
                self.scale = autocvar_g_nexball_viewmodel_scale;
@@ -791,13 +813,13 @@ float ball_customize()
                        self.effects |= EF_FLAME;
                else
                        self.effects &= ~EF_FLAME;
-       }       
+       }
        else
        {
                self.effects &= ~EF_FLAME;
                self.scale = 1;
        }
-               
+
        return TRUE;
 }
 
@@ -833,7 +855,7 @@ float w_nexball_weapon(float req)
                        weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
                }
        }
-       else if(req == WR_PRECACHE)
+       else if(req == WR_INIT)
        {
                precache_model("models/weapons/g_porto.md3");
                precache_model("models/weapons/v_porto.md3");
@@ -845,7 +867,7 @@ float w_nexball_weapon(float req)
        }
        else if(req == WR_SETUP)
        {
-               weapon_setup(WEP_PORTO);
+               //weapon_setup(WEP_PORTO);
        }
        // No need to check WR_CHECKAMMO* or WR_AIM, it should always return TRUE
        return TRUE;
@@ -859,34 +881,22 @@ MUTATOR_HOOKFUNCTION(nexball_BallDrop)
        return 0;
 }
 
-MUTATOR_HOOKFUNCTION(nexball_BuildMutatorsString)
-{
-       ret_string = strcat(ret_string, ":NB");
-       return 0;
-}
-
-MUTATOR_HOOKFUNCTION(nexball_BuildMutatorsPrettyString)
-{
-       ret_string = strcat(ret_string, ", NexBall");
-       return 0;
-}
-
 MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink)
 {
        makevectors(self.v_angle);
        if(nexball_mode & NBM_BASKETBALL)
-       {               
+       {
                if(self.ballcarried)
                {
                        // 'view ball'
-                       self.ballcarried.velocity = self.velocity;                      
+                       self.ballcarried.velocity = self.velocity;
                        self.ballcarried.customizeentityforclient = ball_customize;
-                       
-                       setorigin(self.ballcarried, self.origin + self.view_ofs + 
-                                         v_forward * autocvar_g_nexball_viewmodel_offset_x + 
-                                         v_right * autocvar_g_nexball_viewmodel_offset_y + 
-                                         v_up * autocvar_g_nexball_viewmodel_offset_z);        
-                                         
+
+                       setorigin(self.ballcarried, self.origin + self.view_ofs +
+                                         v_forward * autocvar_g_nexball_viewmodel_offset_x +
+                                         v_right * autocvar_g_nexball_viewmodel_offset_y +
+                                         v_up * autocvar_g_nexball_viewmodel_offset_z);
+
                        // 'safe passing'
                        if(autocvar_g_nexball_safepass_maxdist)
                        {
@@ -895,50 +905,50 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink)
                                        //centerprint(self, sprintf("Lost lock on %s", self.ballcarried.enemy.netname));
                                        self.ballcarried.enemy = world;
                                }
-                                       
-                               
+
+
                                //tracebox(self.origin + self.view_ofs, '-2 -2 -2', '2 2 2', self.origin + self.view_ofs + v_forward * autocvar_g_nexball_safepass_maxdist);
                                crosshair_trace(self);
-                               if( trace_ent && 
+                               if( trace_ent &&
                                        IS_CLIENT(trace_ent) &&
                                        trace_ent.deadflag == DEAD_NO &&
                                        trace_ent.team == self.team &&
                                        vlen(trace_ent.origin - self.origin) <= autocvar_g_nexball_safepass_maxdist )
                                {
-                                       
+
                                        //if(self.ballcarried.enemy != trace_ent)
                                        //      centerprint(self, sprintf("Locked to %s", trace_ent.netname));
                                        self.ballcarried.enemy = trace_ent;
                                        self.ballcarried.wait = time + autocvar_g_nexball_safepass_holdtime;
-                                       
-                                       
+
+
                                }
                        }
                }
                else
-               {                       
+               {
                        if(self.weaponentity.weapons)
                        {
                                self.weapons = self.weaponentity.weapons;
-                               weapon_action(WEP_PORTO, WR_RESETPLAYER);
+                               WEP_ACTION(WEP_PORTO, WR_RESETPLAYER);
                                self.switchweapon = self.weaponentity.switchweapon;
                                W_SwitchWeapon(self.switchweapon);
-                               
+
                self.weaponentity.weapons = '0 0 0';
                        }
                }
-               
+
        }
-       
+
        nexball_setstatus();
-       
+
        return FALSE;
 }
 
 MUTATOR_HOOKFUNCTION(nexball_PlayerSpawn)
-{      
+{
        self.weaponentity.weapons = '0 0 0';
-       
+
        if(nexball_mode & NBM_BASKETBALL)
                self.weapons |= WEPSET_PORTO;
        else
@@ -947,10 +957,37 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerSpawn)
        return FALSE;
 }
 
+MUTATOR_HOOKFUNCTION(nexball_PlayerPhysics)
+{
+       if(self.ballcarried)
+       {
+               self.stat_sv_airspeedlimit_nonqw *= autocvar_g_nexball_basketball_carrier_highspeed;
+               self.stat_sv_maxspeed *= autocvar_g_nexball_basketball_carrier_highspeed;
+       }
+       return FALSE;
+}
+
 MUTATOR_HOOKFUNCTION(nexball_SetStartItems)
 {
        start_items |= IT_UNLIMITED_SUPERWEAPONS; // FIXME BAD BAD BAD BAD HACK, NEXBALL SHOULDN'T ABUSE PORTO'S WEAPON SLOT
-       
+
+       return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing)
+{
+       if(self.weapon == WEP_MORTAR)
+               return TRUE;
+
+       return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(nexball_FilterItem)
+{
+       if(self.classname == "droppedweapon")
+       if(self.weapon == WEP_MORTAR)
+               return TRUE;
+
        return FALSE;
 }
 
@@ -959,11 +996,12 @@ MUTATOR_DEFINITION(gamemode_nexball)
        MUTATOR_HOOK(PlayerDies, nexball_BallDrop, CBC_ORDER_ANY);
        MUTATOR_HOOK(MakePlayerObserver, nexball_BallDrop, CBC_ORDER_ANY);
        MUTATOR_HOOK(ClientDisconnect, nexball_BallDrop, CBC_ORDER_ANY);
-       MUTATOR_HOOK(BuildMutatorsPrettyString, nexball_BuildMutatorsPrettyString, CBC_ORDER_ANY);
-       MUTATOR_HOOK(BuildMutatorsString, nexball_BuildMutatorsString, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerSpawn, nexball_PlayerSpawn, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerPreThink, nexball_PlayerPreThink, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerPhysics, nexball_PlayerPhysics, CBC_ORDER_ANY);
        MUTATOR_HOOK(SetStartItems, nexball_SetStartItems, CBC_ORDER_ANY);
+       MUTATOR_HOOK(ForbidThrowCurrentWeapon, nexball_ForbidThrowing, CBC_ORDER_ANY);
+       MUTATOR_HOOK(FilterItem, nexball_FilterItem, CBC_ORDER_ANY);
 
        MUTATOR_ONADD
        {
@@ -973,6 +1011,8 @@ MUTATOR_DEFINITION(gamemode_nexball)
                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);
 
+               W_Porto(WR_INIT); // abuse
+
                // General settings
                /*
                CVTOV(g_nexball_football_boost_forward);   //100