#include "sv_mmm.qh"
//set g_mmm_sleuth_count 0.125 "number of players who will become sleuths, set between 0 and 0.9 to use a multiplier of the current players, or 1 and above to specify an exact number of players"
-//float autocvar_g_mmm_sleuth_count = 0.125; //I don't think that it won't be used...
+//float autocvar_g_mmm_sleuth_count = 0.125; //I don't think that it'll be used...
float autocvar_g_mmm_civilian_count = 0.625;
//float autocvar_g_mmm_murderer_count = 0.25;
float autocvar_g_mmm_round_timelimit = 180;
bool autocvar_g_mmm_reward_sleuth = true; //sleuth reward if investigated corpses
float autocvar_g_mmm_max_karma_points = 1000; //LegendGuard sets Karma points 21-02-2021
float autocvar_g_mmm_min_karma_points = 400;
-int autocvar_g_mmm_karma_bankick_tool = 0; //LegendGuard sets a ban tool for server admins 11-03-2021
+int autocvar_g_mmm_karma_bankick_tool = 1; //LegendGuard sets a ban tool for server admins 11-03-2021
float autocvar_g_mmm_karma_bantime = 1800; //karma ban seconds
bool autocvar_g_mmm_karma_damageactive = true; //LegendGuard sets Karma damage setting if active 20-03-2021
float autocvar_g_mmm_karma_severity = 0.25;
-
+float autocvar_g_mmm_karma_damagepunishmentdeal = 20; //LegendGuard sets Karma punishment damage setting if player kills an ally 28-03-2021
// Sleuth is a created team, this team is added inside Civilians team
void mmm_FakeTimeLimit(entity e, float t)
{
switch (autocvar_g_mmm_karma_bankick_tool)
{
+ //do nothing
+ case 0: return;
//force to spec
- case 0: PutObserverInServer(it); return;
+ case 1: PutObserverInServer(it); return;
//kick
- case 1: dropclient(it); return;
+ case 2: dropclient(it); return;
//ban and kick
- case 2: Ban_KickBanClient(it, bantime, masksize, "Too low karma"); return;
- //force to spec
+ case 3: Ban_KickBanClient(it, bantime, masksize, "Too low karma"); return;
default: PutObserverInServer(it); return;
}
}
void karmaLoseDifference(entity attacker, entity target)
{
- if (autocvar_g_mmm_karma_severity <= 0)
+ if (autocvar_g_mmm_karma_severity <= 0.09)
autocvar_g_mmm_karma_severity = 0.1;
else if (autocvar_g_mmm_karma_severity > 1)
autocvar_g_mmm_karma_severity = 1;
//BASIC MATH THEORY: example: 1000 * 0.3 * (0.1 + 0.4) * 0.25 // karma points reduce when player attacked to other player
if (target.karmapoints < attacker.karmapoints)
- {
+ {
float decreasekarma = - ( target.karmapoints * random() * ( 0.1 + random() ) * autocvar_g_mmm_karma_severity );
GameRules_scoring_add(attacker, MMM_KARMA, decreasekarma);
attacker.karmapoints = attacker.karmapoints + decreasekarma;
float increasekarma = ( autocvar_g_mmm_min_karma_points * random() * ( 0.1 + random() ) * 0.12 );
GameRules_scoring_add(it, MMM_KARMA, increasekarma);
it.karmapoints = it.karmapoints + increasekarma;
+ karma_Control(it);
}
void mmm_UpdateScores(bool timed_out)
{
karmaWinDifference(it);
//PrintToChatAll(sprintf("^2REWARD ^7it.karmapoints: ^1%f", it.karmapoints));
- karma_Control(it);
}
//Sleuth reward after investigated a corpse
karmaWinDifference(it);
it.investigated = false;
}
- karma_Control(it);
}
- if(it.mmm_status == MMM_STATUS_CIVILIAN)
- {
- karmaWinDifference(it);
- //PrintToChatAll(sprintf("^2CIVILIAN ^7it.karmapoints: ^1%f", it.karmapoints));
- karma_Control(it);
- }
- else if(it.mmm_status == MMM_STATUS_MURDERER)
+ if(it.mmm_status == MMM_STATUS_MURDERER)
{
karmaWinDifference(it);
//PrintToChatAll(sprintf("^1MURDERER ^7it.karmapoints: ^1%f", it.karmapoints));
- karma_Control(it);
}
}
});
if(IS_PLAYER(it))
nades_Clear(it);
mmm_FakeTimeLimit(it, -1);
+ karma_Control(it);
});
mmm_UpdateScores(true);
nades_Clear(it);
}
mmm_FakeTimeLimit(it, -1);
+ karma_Control(it);
});
return 1;
}
+void Karma_WarningCheck(entity it)
+{
+ float totalmeankarma = ((autocvar_g_mmm_max_karma_points + autocvar_g_mmm_min_karma_points + it.karmapoints) / 3);
+ if (it.karmapoints <= totalmeankarma)
+ {
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_INFO, INFO_MMM_KARMAWARNING);
+ //centerprint(it, strcat(BOLD_OPERATOR, "^1KARMA WARNING!\n^3Here, have the Rifle!"));
+ GiveWeapon(it, WEP_RIFLE.m_id, OP_PLUS, 1);
+ }
+}
+
void mmm_RoundStart()
{
allowed_to_spawn = boolean(warmup_stage);
int playercount = 0;
-
+
FOREACH_CLIENT(true,
{
if(IS_PLAYER(it) && !IS_DEAD(it))
FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
{
- float totalmeankarma = ((autocvar_g_mmm_max_karma_points + autocvar_g_mmm_min_karma_points + it.karmapoints) / 3);
karma_Control(it);
it.activekillerrole = false;
if(it.mmm_status == MMM_STATUS_CIVILIAN)
{
- SetResource(it, RES_SHELLS, 10);
- SetResource(it, RES_BULLETS, 20);
- SetResource(it, RES_ROCKETS, 10);
- SetResource(it, RES_CELLS, 10);
- if (it.karmapoints <= totalmeankarma)
- {
- centerprint(it, strcat(BOLD_OPERATOR, "^1KARMA WARNING!\n^3Here, have the Rifle!"));
- GiveWeapon(it, WEP_RIFLE.m_id, OP_PLUS, 1);
- }
+ Karma_WarningCheck(it);
//Gives Mine Layer weapon to the player
GiveWeapon(it, WEP_MINE_LAYER.m_id, OP_PLUS, 1);
Send_Notification(NOTIF_ONE_ONLY, it, MSG_CENTER, CENTER_MMM_CIVILIAN);
}
else if(it.mmm_status == MMM_STATUS_MURDERER)
{
- SetResource(it, RES_SHELLS, 10);
- SetResource(it, RES_BULLETS, 20);
- SetResource(it, RES_ROCKETS, 10);
- SetResource(it, RES_CELLS, 10);
- if (it.karmapoints <= totalmeankarma)
- {
- centerprint(it, strcat(BOLD_OPERATOR, "^1KARMA WARNING!\n^3Here, have the Rifle!"));
- GiveWeapon(it, WEP_RIFLE.m_id, OP_PLUS, 1);
- }
+ Karma_WarningCheck(it);
//Gives Mine Layer weapon to the player
GiveWeapon(it, WEP_MINE_LAYER.m_id, OP_PLUS, 1);
Send_Notification(NOTIF_ONE_ONLY, it, MSG_CENTER, CENTER_MMM_MURDERER);
}
else if(it.mmm_status == MMM_STATUS_SLEUTH)
{
- SetResource(it, RES_ROCKETS, 10);
- if (it.karmapoints <= totalmeankarma)
- {
- centerprint(it, strcat(BOLD_OPERATOR, "^1KARMA WARNING!\n^3Here, have the Rifle!"));
- GiveWeapon(it, WEP_RIFLE.m_id, OP_PLUS, 1);
- }
+ Karma_WarningCheck(it);
//Gives Shockwave and Mine Layer weapon to the player
GiveWeapon(it, WEP_SHOCKWAVE.m_id, OP_PLUS, 1);
GiveWeapon(it, WEP_MINE_LAYER.m_id, OP_PLUS, 1);
Send_Notification(NOTIF_ONE_ONLY, it, MSG_CENTER, CENTER_MMM_SLEUTH);
Send_Notification(NOTIF_ONE_ONLY, it, MSG_INFO, INFO_MMM_SLEUTH);
- PrintToChatAll(sprintf("%s is ^4Sleuth^7!", it.netname));
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_MMM_WHOISSLEUTH, it.netname);
}
mmm_FakeTimeLimit(it, round_handler_GetEndTime());
});
int playercount = 0;
FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
- {
+ {
//PrintToChatAll(sprintf("it.karmapoints ^5begin: ^3%f",it.karmapoints));
- //Karma points start
- if (it.karmastarted != true)
- {
- GameRules_scoring_add(it, MMM_KARMA, autocvar_g_mmm_max_karma_points - it.karmapoints);
- it.karmapoints = autocvar_g_mmm_max_karma_points;
- it.karmastarted = true;
- }
karma_Control(it);
++playercount;
//PrintToChatAll(sprintf("it.karmapoints ^6end: ^3%f",it.karmapoints));
{
karmaLoseDifference(frag_attacker, frag_target);
GiveFrags(frag_attacker, frag_target, ((autocvar_g_mmm_punish_teamkill) ? -1 : -2), frag_deathtype, wep_ent.weaponentity_fld);
- karma_Control(frag_attacker);
frag_target.whokilled = frag_attacker.netname;
}
checkWeaponDeathtype(frag_target, frag_deathtype);
}
- //TODO: try to do a "find out" if a sleuth can see who fragged to who if possible 21-02-2021
M_ARGV(5, bool) = true; // anonymous attacker
}
float damage = M_ARGV(4, float);
vector force = M_ARGV(6, vector);
string corpsemessagestrcat = "";
+ string corpsemsginfo = "";
if (autocvar_g_mmm_karma_damageactive != false)
{
}
}
- //SLEUTH CORPSE DETECTION SKILL 21-03-2021
- if (attacker.mmm_status == MMM_STATUS_SLEUTH)
+ //CORPSE DETECTION SKILL 21-03-2021
+ if(IS_DEAD(target))
{
- if(IS_DEAD(target))
+ //Shockwave weapon as radar gun to check the corpses 22-03-2021
+ if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE))
{
- //Shockwave weapon as radar gun to check the corpses 22-03-2021
- if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE))
+ if (target.killedwithweapon == "")
+ target.killedwithweapon = "UNKNOWN CAUSE";
+
+ if (target.activekillerrole != true)
{
- if (target.killedwithweapon == "")
- target.killedwithweapon = "UNKNOWN CAUSE";
-
- if (target.activekillerrole != true)
- {
- target.killerrole = "";
- target.activekillerrole = false;
- }
+ target.killerrole = "";
+ target.activekillerrole = false;
+ }
- string killedbyphrase = strcat("\n^3Killed by:^7 ", target.whokilled, target.killerrole);
- string wepkilledphrase = strcat("\n^3Cause:^7 ", target.killedwithweapon);
- if (target.whokilled == "")
- {
- killedbyphrase = "";
- if (target.killedwithweapon == "")
- wepkilledphrase = "\n^3Cause:^7 UNKNOWN CAUSE";
- }
+ string killedbyphrase = strcat("^3Killed by:^7 ", target.whokilled, target.killerrole);
+ string wepkilledphrase = strcat("^3Cause:^7 ", target.killedwithweapon);
+ if (target.whokilled == "")
+ {
+ killedbyphrase = "";
+ if (target.killedwithweapon == "")
+ wepkilledphrase = "^3Cause:^7 UNKNOWN CAUSE";
+ }
- damage = 0;
- force = '0 0 0';
- if (target.mmm_status == MMM_STATUS_CIVILIAN)
- {
- //try to add centerprint message for chat privately if possible
- corpsemessagestrcat = strcat("\n^3Name:^7 ", target.netname, "\n^3Role: ^2Civilian", killedbyphrase, wepkilledphrase);
- centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));//("\n^6Name^3:^7 ", target.netname, "\n^5Role^3: ^2Civilian\n", "^1Killed by^3:^7 ", target.whokilled)));
- }
- else if (target.mmm_status == MMM_STATUS_MURDERER)
- {
- corpsemessagestrcat = strcat("\n^3Name:^7 ", target.netname, "\n^3Role: ^1Murderer", killedbyphrase, wepkilledphrase);
- centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));//("\n^6Name^3:^7 ", target.netname, "\n^5Role^3: ^1Murderer\n", "^1Killed by^3:^7 ", target.whokilled)));
- }
- else if (target.mmm_status == MMM_STATUS_SLEUTH)
- {
- corpsemessagestrcat = strcat("\n^3Name:^7 ", target.netname, "\n^3Role: ^4Sleuth", killedbyphrase, wepkilledphrase);
- centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));//("\n^6Name^3:^7 ", target.netname, "\n^5Role^3: ^4Sleuth\n", "^1Killed by^3:^7 ", target.whokilled)));
- }
- attacker.investigated = true;
+ damage = 0;
+ force = '0 0 0';
+ if (target.mmm_status == MMM_STATUS_CIVILIAN)
+ {
+ //try to add centerprint message for chat privately if possible
+ corpsemessagestrcat = strcat("^5DEAD PLAYER DETAILS^7: \n^3Name:^7 ", target.netname, "\n^3Role: ^2Civilian", "\n", killedbyphrase, "\n", wepkilledphrase);
+ corpsemsginfo = strcat("^5DEAD PLAYER DETAILS^7: ^3Name:^7 ", target.netname, " ^3Role: ^2Civilian", " ", killedbyphrase, " ", wepkilledphrase);
+ //centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));
+ Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_CENTER, CENTER_MMM_CORPSEDETECTION, corpsemessagestrcat);
+ Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_INFO, INFO_MMM_CORPSEDETECTION, corpsemsginfo);
}
+ else if (target.mmm_status == MMM_STATUS_MURDERER)
+ {
+ corpsemessagestrcat = strcat("^5DEAD PLAYER DETAILS^7: \n^3Name:^7 ", target.netname, "\n^3Role: ^1Murderer", "\n", killedbyphrase, "\n", wepkilledphrase);
+ corpsemsginfo = strcat("^5DEAD PLAYER DETAILS^7: ^3Name:^7 ", target.netname, " ^3Role: ^1Murderer", " ", killedbyphrase, " ", wepkilledphrase);
+ //centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));
+ Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_CENTER, CENTER_MMM_CORPSEDETECTION, corpsemessagestrcat);
+ Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_INFO, INFO_MMM_CORPSEDETECTION, corpsemsginfo);
+ }
+ else if (target.mmm_status == MMM_STATUS_SLEUTH)
+ {
+ corpsemessagestrcat = strcat("^5DEAD PLAYER DETAILS^7: \n^3Name:^7 ", target.netname, "\n^3Role: ^4Sleuth", "\n", killedbyphrase, "\n", wepkilledphrase);
+ corpsemsginfo = strcat("^5DEAD PLAYER DETAILS^7: ^3Name:^7 ", target.netname, " ^3Role: ^4Sleuth", " ", killedbyphrase, " ", wepkilledphrase);
+ //centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));
+ Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_CENTER, CENTER_MMM_CORPSEDETECTION, corpsemessagestrcat);
+ Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_INFO, INFO_MMM_CORPSEDETECTION, corpsemsginfo);
+ }
+ attacker.investigated = true;
}
}
MUTATOR_HOOKFUNCTION(mmm, PlayerPreThink)
{
entity player = M_ARGV(0, entity);
-
+ int playercount = 0;
+ bool playercheck = false;
+
+ if (playercheck != true)
+ {
+ FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
+ {
+ ++playercount;
+ });
+ playercheck = true;
+ }
+
+ //if the murderer is still here around, then avoid illogical winning
+ if (playercheck == true)
+ {
+ FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
+ {
+ if (playercount == 3)
+ {
+ if (it.mmm_status == MMM_STATUS_SLEUTH)
+ it.mmm_status = MMM_STATUS_CIVILIAN;
+ }
+ });
+ }
+
if(IS_PLAYER(player) || player.caplayer)
{
+ if (player.karmaspectated != true)
+ {
+ if (CS(player).scorekeeper.(scores(SP_MMM_KARMA)) <= 0) //wtf? Visualization works 100% correct?
+ GameRules_scoring_add(player, MMM_KARMA, player.karmapoints);
+ player.karmaspectated = true;
+ }
// update the scoreboard colour display to out the real killer at the end of the round
// running this every frame to avoid cheats
int plcolor = MMM_COLOR_CIVILIAN;
plcolor = MMM_COLOR_SLEUTH;
setcolor(player, plcolor);
}
+ if(warmup_stage)
+ player.karmastarted = false;
//CORPSE FEATURE 10-03-2021
if (IS_DEAD(player))
MUTATOR_HOOKFUNCTION(mmm, PlayerSpawn)
{
entity player = M_ARGV(0, entity);
+
+ //Karma points start
+ if (player.karmastarted != true)
+ {
+ CS(player).scorekeeper.(scores(SP_MMM_KARMA)) = 0; //full karma reset lol
+ player.karmapoints = autocvar_g_mmm_max_karma_points;
+ GameRules_scoring_add(player, MMM_KARMA, player.karmapoints);
+ player.karmastarted = true;
+ }
player.mmm_status = 0;
player.mmm_validkills = 0;
frag_target.health = 0;
if (!warmup_stage)
- {
eliminatedPlayers.SendFlags |= 1;
- if (IS_BOT_CLIENT(frag_target))
- bot_clear(frag_target);
- }
//if(frag_attacker.mmm_status == frag_target.mmm_status)
// killed an ally! punishment is sentenced
if (frag_target.mmm_status == MMM_STATUS_CIVILIAN)
{
//PrintToChatAll("^1DEBUG^7: ^4SLEUTH ^1DAMAGE/DEAD^7 HAS TAKEN!");
- //30 damage points deal
- Damage(frag_attacker, frag_attacker, frag_attacker, 30, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
+ Damage(frag_attacker, frag_attacker, frag_attacker, autocvar_g_mmm_karma_damagepunishmentdeal, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
}
}
if (frag_attacker.mmm_status == MMM_STATUS_CIVILIAN)
if (frag_target.mmm_status == MMM_STATUS_SLEUTH)
{
//PrintToChatAll("^1DEBUG^7: ^2CIVILIAN ^1DAMAGE/DEAD^7 HAS TAKEN!");
- //30 damage points deal
- Damage(frag_attacker, frag_attacker, frag_attacker, 30, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
+ Damage(frag_attacker, frag_attacker, frag_attacker, autocvar_g_mmm_karma_damagepunishmentdeal, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
+ }
+ }
+ if (frag_attacker.mmm_status == MMM_STATUS_MURDERER)
+ {
+ if (frag_target.mmm_status == MMM_STATUS_MURDERER)
+ {
+ //PrintToChatAll("^1DEBUG^7: ^1MURDERER ^1DAMAGE/DEAD^7 HAS TAKEN!");
+ Damage(frag_attacker, frag_attacker, frag_attacker, autocvar_g_mmm_karma_damagepunishmentdeal, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
}
}
return true;
MUTATOR_HOOKFUNCTION(mmm, MakePlayerObserver)
{
- // LegendGuard, here is where spectators shouldn't talk to any players to say the hints or who is who 21-10-2021
entity player = M_ARGV(0, entity);
if (IS_PLAYER(player) && !IS_DEAD(player))
mmm_LastPlayerForTeam_Notify(player);
+ if (player.karmaspectated == true)
+ player.karmaspectated = false;
if (player.killindicator_teamchange == -2) // player wants to spectate
player.caplayer = 0;
if (player.caplayer)
MUTATOR_HOOKFUNCTION(mmm, GiveFragsForKill, CBC_ORDER_FIRST)
{
entity frag_attacker = M_ARGV(0, entity);
- if(!warmup_stage && round_handler_IsActive() && round_handler_IsRoundStarted())
+ if(!warmup_stage && round_handler_IsActive() && round_handler_IsRoundStarted())
frag_attacker.mmm_validkills += M_ARGV(2, float);
M_ARGV(2, float) = 0; // score will be given to the winner when the round ends
return true;
return true;
}
+//if server admin sets "sv_ready_restart_after_countdown 1", will avoid possible visual failure for karma in the scoreboard
+MUTATOR_HOOKFUNCTION(mmm, ReadLevelCvars)
+{
+ sv_ready_restart_after_countdown = 0;
+}
+
MUTATOR_HOOKFUNCTION(mmm, Bot_FixCount, CBC_ORDER_EXCLUSIVE)
{
FOREACH_CLIENT(IS_REAL_CLIENT(it), {