From: Samual Lenks Date: Tue, 7 May 2013 05:37:55 +0000 (-0400) Subject: Merge remote-tracking branch 'origin/master' into Mario/lms_updates X-Git-Tag: xonotic-v0.7.0~60^2 X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=94a967120c8bfe0d4ffd95690b97e5af297dfc05 Merge remote-tracking branch 'origin/master' into Mario/lms_updates Conflicts: qcsrc/server/arena.qc qcsrc/server/cl_client.qc qcsrc/server/cl_weapons.qc qcsrc/server/scores.qc --- 94a967120c8bfe0d4ffd95690b97e5af297dfc05 diff --cc qcsrc/server/cl_client.qc index 84bbd1896f,5d29bf7e15..2f9c0d8312 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@@ -2616,10 -2583,10 +2570,10 @@@ void PlayerPreThink (void if(frametime) player_anim(); button_pressed = (self.BUTTON_ATCK || self.BUTTON_JUMP || self.BUTTON_ATCK2 || self.BUTTON_HOOK || self.BUTTON_USE); - force_respawn = (g_ca || g_cts || autocvar_g_forced_respawn); - ++ if (self.deadflag == DEAD_DYING) { - if(force_respawn) + if(self.respawn_flags & RESPAWN_FORCE) self.deadflag = DEAD_RESPAWNING; else if(!button_pressed) self.deadflag = DEAD_DEAD; diff --cc qcsrc/server/cl_weapons.qc index 40c616a85c,57b1cf4f4d..0014e9182d --- a/qcsrc/server/cl_weapons.qc +++ b/qcsrc/server/cl_weapons.qc @@@ -301,8 -301,8 +301,6 @@@ float W_IsWeaponThrowable(float w return 0; if (g_weaponarena) return 0; - if (g_ca) - if (g_lms) -- return 0; if (g_cts) return 0; if (g_nexball && w == WEP_GRENADE_LAUNCHER) diff --cc qcsrc/server/mutators/gamemode_lms.qc index cb8f63bbec,0000000000..681a1d433a mode 100644,000000..100644 --- a/qcsrc/server/mutators/gamemode_lms.qc +++ b/qcsrc/server/mutators/gamemode_lms.qc @@@ -1,249 -1,0 +1,249 @@@ +// main functions +float LMS_NewPlayerLives() +{ + float fl; + fl = autocvar_fraglimit; + if(fl == 0) + fl = 999; + + // first player has left the game for dying too much? Nobody else can get in. + if(lms_lowest_lives < 1) + return 0; + + if(!autocvar_g_lms_join_anytime) + if(lms_lowest_lives < fl - autocvar_g_lms_last_join) + return 0; + + return bound(1, lms_lowest_lives, fl); +} + +// mutator hooks +MUTATOR_HOOKFUNCTION(lms_PlayerSpawn) +{ + if(IS_PLAYER(self)) + if(restart_mapalreadyrestarted || (time < game_starttime)) + PlayerScore_Add(self, SP_LMS_LIVES, LMS_NewPlayerLives()); + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(lms_RemovePlayer) +{ + // Only if the player cannot play at all + if(PlayerScore_Add(self, SP_LMS_RANK, 0) == 666) + self.frags = FRAGS_SPECTATOR; + else + self.frags = FRAGS_LMS_LOSER; + + if(self.killcount != -666) + if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0 && self.lms_spectate_warning != 2) + Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_LMS_NOLIVES, self.netname); + else + Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_LMS_FORFEIT, self.netname); + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(lms_ClientConnect) +{ + self.classname = "player"; + campaign_bots_may_start = 1; + + if(PlayerScore_Add(self, SP_LMS_LIVES, LMS_NewPlayerLives()) <= 0) + { + PlayerScore_Add(self, SP_LMS_RANK, 666); + self.frags = FRAGS_SPECTATOR; + } + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(lms_PlayerThink) +{ + if(self.deadflag == DEAD_DYING) + self.deadflag = DEAD_RESPAWNING; + + if not(self.deadflag) + if(autocvar_g_lms_campcheck_interval) + { + vector dist; + + // calculate player movement (in 2 dimensions only, so jumping on one spot doesn't count as movement) + dist = self.prevorigin - self.origin; + dist_z = 0; + self.lms_traveled_distance += fabs(vlen(dist)); + + if((autocvar_g_campaign && !campaign_bots_may_start) || (time < game_starttime)) + { + self.lms_nextcheck = time + autocvar_g_lms_campcheck_interval*2; + self.lms_traveled_distance = 0; + } + + if(time > self.lms_nextcheck) + { + if(self.lms_traveled_distance < autocvar_g_lms_campcheck_distance) + { + Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_LMS_CAMPCHECK); + if(self.vehicle) + Damage(self.vehicle, self, self, autocvar_g_lms_campcheck_damage * 2, DEATH_CAMP, self.vehicle.origin, '0 0 0'); + else + Damage(self, self, self, bound(0, autocvar_g_lms_campcheck_damage, self.health + self.armorvalue * autocvar_g_balance_armor_blockpercent + 5), DEATH_CAMP, self.origin, '0 0 0'); + } + self.lms_nextcheck = time + autocvar_g_lms_campcheck_interval; + self.lms_traveled_distance = 0; + } + } + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(lms_PlayerDamage) +{ + if(IS_PLAYER(frag_target)) + if(IS_PLAYER(frag_attacker)) + if(frag_attacker != frag_target) + { + frag_target.lms_traveled_distance = autocvar_g_lms_campcheck_distance; + frag_attacker.lms_traveled_distance = autocvar_g_lms_campcheck_distance; + } + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(lms_ForbidThrowing) +{ + // forbode! + return TRUE; +} + +MUTATOR_HOOKFUNCTION(lms_GiveFragsForKill) +{ + // remove a life + float tl; + tl = PlayerScore_Add(frag_target, SP_LMS_LIVES, -1); + if(tl < lms_lowest_lives) + lms_lowest_lives = tl; + if(tl <= 0) + { + if(!lms_next_place) + lms_next_place = player_count; + else + lms_next_place = min(lms_next_place, player_count); + PlayerScore_Add(frag_target, SP_LMS_RANK, lms_next_place); // won't ever spawn again + --lms_next_place; + } + frag_score = 0; + + return TRUE; +} + +MUTATOR_HOOKFUNCTION(lms_SetStartItems) +{ + start_items &~= IT_UNLIMITED_AMMO; + start_ammo_shells = cvar("g_lms_start_ammo_shells"); + start_ammo_nails = cvar("g_lms_start_ammo_nails"); + start_ammo_rockets = cvar("g_lms_start_ammo_rockets"); + start_ammo_cells = cvar("g_lms_start_ammo_cells"); + start_ammo_fuel = cvar("g_lms_start_ammo_fuel"); + start_health = cvar("g_lms_start_health"); + start_armorvalue = cvar("g_lms_start_armor"); + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(lms_KeepScore) +{ + // don't clear player score + return TRUE; +} + +MUTATOR_HOOKFUNCTION(lms_FilterItem) +{ + if(autocvar_g_lms_extra_lives) + if(self.classname == "item_health_mega") + { + self.max_health = 1; + return FALSE; + } + + return TRUE; +} + +MUTATOR_HOOKFUNCTION(lms_ItemTouch) +{ + // give extra lives for mega health + if(self.items & IT_HEALTH) + { + Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_EXTRALIVES); + PlayerScore_Add(other, SP_LMS_LIVES, autocvar_g_lms_extra_lives); + } + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(lms_BotSpawn) +{ + // temporary hack to give bots lives + if(PlayerScore_Add(self, SP_LMS_LIVES, LMS_NewPlayerLives()) <= 0) + { + PlayerScore_Add(self, SP_LMS_RANK, 666); + self.frags = FRAGS_SPECTATOR; + } + + return FALSE; +} + +// scoreboard stuff +void lms_ScoreRules() +{ + ScoreRules_basics(0, 0, 0, FALSE); + ScoreInfo_SetLabel_PlayerScore(SP_LMS_LIVES, "lives", SFL_SORT_PRIO_SECONDARY); + ScoreInfo_SetLabel_PlayerScore(SP_LMS_RANK, "rank", SFL_LOWER_IS_BETTER | SFL_RANK | SFL_SORT_PRIO_PRIMARY | SFL_ALLOW_HIDE); + ScoreRules_basics_end(); +} + +void lms_Initialize() +{ + lms_lowest_lives = 9999; + lms_next_place = 0; + + lms_ScoreRules(); +} + +MUTATOR_DEFINITION(gamemode_lms) +{ + MUTATOR_HOOK(PlayerSpawn, lms_PlayerSpawn, CBC_ORDER_ANY); + MUTATOR_HOOK(MakePlayerObserver, lms_RemovePlayer, CBC_ORDER_ANY); + MUTATOR_HOOK(ClientConnect, lms_ClientConnect, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerPreThink, lms_PlayerThink, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerDamage_Calculate, lms_PlayerDamage, CBC_ORDER_ANY); + MUTATOR_HOOK(ForbidThrowCurrentWeapon, lms_ForbidThrowing, CBC_ORDER_ANY); + MUTATOR_HOOK(GiveFragsForKill, lms_GiveFragsForKill, CBC_ORDER_ANY); + MUTATOR_HOOK(SetStartItems, lms_SetStartItems, CBC_ORDER_ANY); - MUTATOR_HOOK(PlayerClearScore, lms_KeepScore, CBC_ORDER_ANY); ++ MUTATOR_HOOK(ForbidPlayerScore_Clear, lms_KeepScore, CBC_ORDER_ANY); + MUTATOR_HOOK(FilterItem, lms_FilterItem, CBC_ORDER_ANY); + MUTATOR_HOOK(ItemTouch, lms_ItemTouch, CBC_ORDER_ANY); + MUTATOR_HOOK(HavocBot_ChooseRule, lms_BotSpawn, CBC_ORDER_ANY); + + MUTATOR_ONADD + { + if(time > 1) // game loads at time 1 + error("This is a game type and it cannot be added at runtime."); + lms_Initialize(); + } + + MUTATOR_ONROLLBACK_OR_REMOVE + { + // we actually cannot roll back lms_Initialize here + // BUT: we don't need to! If this gets called, adding always + // succeeds. + } + + MUTATOR_ONREMOVE + { + print("This is a game type and it cannot be removed at runtime."); + return -1; + } + + return 0; +} diff --cc qcsrc/server/scores.qc index 3d8460bcb7,4c75c9850a..ad10fa5d53 --- a/qcsrc/server/scores.qc +++ b/qcsrc/server/scores.qc @@@ -256,8 -256,8 +256,8 @@@ float PlayerScore_Clear(entity player if(teamscores_entities_count) return 0; - if(MUTATOR_CALLHOOK(PlayerClearScore)) return 0; - if(g_arena || g_ca) return 0; + if(MUTATOR_CALLHOOK(ForbidPlayerScore_Clear)) return 0; - if(g_lms) return 0; ++ if(g_cts) return 0; // in CTS, you don't lose score by observing if(g_race && g_race_qualifying) return 0; // in qualifying, you don't lose score by observing