Files
SMScripts/scripting/include/fartsy/ass_events.inc
Professor Fartsalot 94696de3ef v.8.4.0 - full audiosystem rewrite again
8th time rewriting it...

+ Make audio manager be an array - one entry for each possible client.
+ Added global audio manager for setting everyone's music at once and ticking all audio managers that are set to tick. This does not apply to clients who are experiencing "an event".
+ Made audio managers check if their clients are valid - if not, stop the manager immediately.
+ Use g_indexBGM for setting global bgm indexes.
+ Automatically set and update music for each client that joins the server
+ Automatically set and update music for each client when the game mode changes
+ Made /song command immediately reflect the current playing song
+ Changed how instant stopping works, unnecessary but yknow, tests???
+ Added a timer to delay music startup on plugin reload
- Removed old timer system used for playing music to new clients in favor of event based system.
2025-08-23 06:25:03 -04:00

254 lines
14 KiB
SourcePawn

//Sync client stats when they leave
public void OnClientDisconnect(int client) {
//Database Ass_Database = Get_Ass_Database();
AudioManager[client].Client = -1;
PrintToServer("[AudioManager @ %i] Client %N disconnected, shutting down gracefully!", client, client);
int steamID = GetSteamAccountID(client);
if (steamID) {
iDmgHealingTotal -= EmnityManager[client].iDamage;
iDmgHealingTotal -= EmnityManager[client].iHealing;
}
if (!Ass_Database || !steamID || steamID <= 10000) return;
char query[256];
char clientName[128];
GetClientInfo(client, "name", clientName, 128);
Format(query, sizeof(query), "INSERT INTO ass_activity (name, steamid, date, seconds) VALUES ('%s', %d, CURRENT_DATE, %d) ON DUPLICATE KEY UPDATE name = '%s', seconds = seconds + VALUES(seconds);", clientName, steamID, GetClientMapTime(client), clientName);
Ass_Database.Query(Database_FastQuery, query);
if (GetClientCount(false) == 0) { CreateTimer(600.0, TimedOperator, 99999);}
}
//Check who spawned and log their class
public Action EventSpawn(Event Spawn_Event, const char[] Spawn_Name, bool Spawn_Broadcast) {
int client = GetClientOfUserId(Spawn_Event.GetInt("userid"));
if (IsValidClient(client)) {
int class = Spawn_Event.GetInt("class");
if (class) AudioManager[client].OnClientRespawned();
int steamID = GetSteamAccountID(client);
if (!Ass_Database || !steamID || !class) return Plugin_Handled;
char strClass[32];
char query[256];
strClass = ClassDefinitions[class - 1];
Format(query, sizeof(query), "UPDATE ass_activity SET class = '%s' WHERE steamid = %i;", strClass, steamID);
Ass_Database.Query(Database_FastQuery, query);
}
return Plugin_Handled;
}
//Log Damage!
public void Event_PlayerHurt(Handle event, const char[] name, bool dontBroadcast) {
int client = GetClientOfUserId(GetEventInt(event, "userid"));
int attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
int damage = GetEventInt(event, "damageamount");
if (IsValidClient(attacker) && attacker != client) {
int steamID = GetSteamAccountID(attacker);
if (!Ass_Database || !steamID) return;
PrintToServer("Adding Damage %i dealt by %N, with index %i", damage, attacker, attacker);
int healer = GetHealerOfClient(attacker);
if (healer != -1){
EmnityManager[healer].iDamage += RoundToFloor(damage * 0.35);
iDmgHealingTotal += RoundToFloor(damage * 0.35);
}
EmnityManager[attacker].iDamage += damage;
iDmgHealingTotal += damage;
char query[256];
Format(query, sizeof(query), "UPDATE ass_activity SET damagedealt = damagedealt + %i, damagedealtsession = damagedealtsession + %i WHERE steamid = %i;", damage, damage, steamID);
Ass_Database.Query(Database_FastQuery, query);
}
}
//Check who died by what and announce it to chat.
public Action EventDeath(Event Spawn_Event, const char[] Spawn_Name, bool Spawn_Broadcast) {
int client = GetClientOfUserId(Spawn_Event.GetInt("userid"));
int attacker = GetClientOfUserId(Spawn_Event.GetInt("attacker"));
int steamid = GetSteamAccountID(client);
if(steamid){
iDmgHealingTotal -= EmnityManager[client].iDamage;
iDmgHealingTotal -= EmnityManager[client].iHealing;
EmnityManager[client].iBossDamage = 0;
EmnityManager[client].iDamage = 0;
EmnityManager[client].iHealing = 0;
}
char name[64];
char weapon[32];
Format(name, sizeof(name), attacker == 0 ? "[INTENTIONAL GAME DESIGN]" : "%N", IsValidClient(attacker) ? client : attacker);
Spawn_Event.GetString("weapon", weapon, sizeof(weapon));
if (0 < client <= MaxClients && IsClientInGame(client)) {
int damagebits = Spawn_Event.GetInt("damagebits");
if (IsValidClient(attacker) && core.sacrificedByClient) SacrificeClient(client, attacker, core.bombReset);
if (!attacker) {
switch (damagebits) {
case 1: { //CRUSH
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N was crushed by a {red}FALLING ROCK FROM OUTER SPACE{white}!", client);
weapon = "Meteor to the Face";
}
case 8: { //BURN
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N was {red}MELTED{white}.", client);
weapon = "Melted by Sharts or Ass Gas";
}
case 16: { //FREEZE
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N was flattened out by a {red}TRAIN{white}!", client);
weapon = "Attempted Train Robbery";
}
case 32: { //FALL
if (WeatherManager.hasTornado) {
switch (GetClientTeam(client)) {
case 2: {
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N was {red}%s{white}!", client, DeathMessage[GetRandomInt(0, 5)]);
weapon = "Yeeted into Orbit via Tornado";
}
case 3: {
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N was {red}%s{white}! ({limegreen}+1 pt{white})", client, DeathMessage[GetRandomInt(0, 5)]);
core.sacPoints++;
CustomSoundEmitter(SFXArray[GetRandomInt(11, 26)].realPath, 65, false, 0, 1.0, 100);
}
}
} else {
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N fell to a {red}CLUMSY PAINFUL DEATH{white}!", client);
weapon = "Tripped on a LEGO";
}
}
case 64: { //BLAST
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N went {red} KABOOM{white}!", client);
weapon = "Gone Kaboom!";
}
case 128: { //CLUB
if (core.canHindenburg) {
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N is {red}CRASHING THE HINDENBURG{white}!!!", client);
weapon = "Crashing the Hindenburg";
}
}
case 256: { //SHOCK
if(core.CodeEntry > 0){
CPrintToChatAll("{darkviolet}[{red}EXTERMINATUS{darkviolet}] {white}Client %N has humliated themselves with an {red}incorrect {white}key entry!", client);
weapon = "Failed FB Code Entry";
int i = GetRandomInt(1, 16);
switch (i) {
case 1, 3, 10: {
FastFire2("BG.Meteorites1", "ForceSpawn", "", 0.0, false);
CPrintToChatAll("{darkviolet}[{red}WARN{darkviolet}] {white}Uh oh, a {red}METEOR{white}has been spotted coming towards Dovah's Ass!!!");
FastFire2("bg.meteorite1", "StartForward", "", 0.1, false);
}
case 2, 5, 16: {
CreateTimer(0.5, TimedOperator, 71);
FastFire2("FB.TankTrain", "TeleportToPathTrack", "Tank01", 0.0, false);
FastFire2("FB.TankTrain", "StartForward", "", 0.25, false);
FastFire2("FB.TankTrain", "SetSpeed", "1", 0.35, false);
FastFire2("FB.Tank", "Enable", "", 1.0, false);
}
case 4, 8, 14: {
CustomSoundEmitter("ambient/alarms/train_horn_distant1.wav", 65, false, 0, 1.0, 100);
FastFire2("TrainSND","PlaySound", "", 0.0, false);
FastFire2("TrainDamage", "Enable", "", 0.0, false);
FastFire2("Train01", "Enable", "", 0.0, false);
CPrintToChatAll("{darkviolet}[{red}WARN{darkviolet}] {orange}KISSONE'S TRAIN{white}is {red}INCOMING{white}. Look out!");
FastFire2("TrainTrain", "TeleportToPathTrack", "TrainTrack01", 0.0, false);
FastFire2("TrainTrain", "StartForward", "", 0.1, false);
}
case 6, 9: {
WeatherManager.canTornado = true;
CreateTimer(1.0, TimedOperator, 41);
}
case 7, 13: {
CPrintToChatAll("{darkviolet}[{red}WARN{darkviolet}] {white}Uh oh, it appears to have started raining a {red}METEOR SHOWER{white}!!!");
core.canSENTMeteors = true;
CreateTimer(1.0, SENTMeteorTimer);
CreateTimer(30.0, TimedOperator, 12);
}
case 11: {
FastFire2("FB.Slice", "Enable", "", 0.0, false);
CustomSoundEmitter("ambient/sawblade_impact1.wav", 65, false, 0, 1.0, 100);
FastFire2("FB.Slice", "Disable", "", 1.0, false);
}
}
}
}
case 512: { //SONIC
CPrintToChatAll("{darkviolet}[{red}EXTERMINATUS{darkviolet}] {white}Client %N has sacrificed themselves with a {forestgreen}correct {white}key entry! Prepare your anus!", client);
sudo(1006);
weapon = "Correct FB Code Entry";
}
case 1024: { //ENERGYBEAM
char EnergyDeath[32];
Format(EnergyDeath, sizeof(EnergyDeath), (core.crusader ? "THE CRUSADER" : core.waveFlags == 1 ? "ONSLAUGHTER" : "LIGHTNING"));
weapon = (core.crusader ? "Crusader" : core.waveFlags == 1 ? "Onslaughter" : "Lightning");
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N has been %s by {red}%s{white}!", client, (core.crusader ? "nuked" : core.waveFlags == 1 ? "deleted" : "struck"), EnergyDeath);
}
case 16384: { //DROWN
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N {red}DROWNED{white}.", client);
weapon = "Darwin Award for Drowning";
}
case 32768: { //PARALYZE
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N has been crushed by a {darkviolet}MYSTERIOUS BLUE BALL{white}!", client);
weapon = "Mysterious Blue Ball";
}
case 65536: { //NERVEGAS
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N has been {red}SLICED TO RIBBONS{white}!", client);
weapon = "FB Code Entry Failed";
}
case 131072: { //POISON
CPrintToChat(client, "{darkviolet}[{red}CORE{darkviolet}] {white}Please don't sit {red}IDLE {white}in the FC Tavern.");
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N was killed for standing in the Tavern instead of helping their team!", client);
weapon = "Idle in FC Tavern..?";
}
case 262144: { //RADIATION
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N was blown away by a {red}NUCLEAR EXPLOSION{white}!", client);
weapon = "Nuclear Explosion";
}
case 524288: { //DROWNRECOVER
CPrintToChatAll("{darkviolet}[{red}CORE{darkviolet}] {white}Client %N experienced {red}TACO BELL{white}!", client);
weapon = "Taco Bell";
}
case 1048576: { //ACID
CPrintToChatAll( isGoobbue ? "{darkviolet}[{red}CORE{darkviolet}] {white}Client %N has been crushed by a {forestgreen}FALLING GOOBBUE FROM OUTER SPACE{white}!" : "{darkviolet}[{red}CORE{darkviolet}] {white}Client %N was deleted by {orange}AN AREA OF EFFECT{white}!", client);
weapon = isGoobbue ? "Falling Goobbue" : "AREA_EFFECT";
}
}
}
//Log if a player killed someone or was killed by a robot
if (attacker != client) {
if (!Ass_Database) return Plugin_Handled;
char query[256];
int steamID = (IsValidClient(attacker) ? GetSteamAccountID(attacker) : GetSteamAccountID(client));
Format(query, sizeof(query), IsValidClient(attacker) && !StrEqual(weapon, "world") ? "UPDATE ass_activity SET kills = kills +1, killssession = killssession + 1, lastkilledname = '%s', lastweaponused = '%s' WHERE steamid = %i;" : !StrEqual(weapon, "world") && !IsValidClient(attacker) ? "UPDATE ass_activity SET deaths = deaths + 1, deathssession = deathssession + 1, killedbyname = '%s', killedbyweapon = '%s' WHERE steamid = %i;" : "RETURN", name, weapon, steamID);
if (StrEqual(query, "RETURN")) return Plugin_Handled;
Ass_Database.Query(Database_FastQuery, query);
}
}
return Plugin_Handled;
}
//When we win
public Action EventWaveComplete(Event Spawn_Event, const char[] Spawn_Name, bool Spawn_Broadcast) {
sudo(300);
CPrintToChatAll("{darkviolet}[{forestgreen}CORE{darkviolet}] {white}You've defeated the wave!");
return Plugin_Handled;
}
//Announce when we are in danger.
public Action EventWarning(Event Spawn_Event,
const char[] Spawn_Name, bool Spawn_Broadcast) {
if (core.doFailsafe) {
core.failsafeCount++;
CPrintToChatAll("%s Counter: %i", failsafe[GetRandomInt(0, sizeof(failsafe) - 1)], core.failsafeCount);
EmitSoundToAll(SFXArray[55].realPath);
PerformWaveFailsafe(GetRandomInt(0,1));
core.doFailsafe = false;
} else CPrintToChatAll("{darkviolet}[{red}WARN{darkviolet}] {darkred}PROFESSOR'S ASS IS ABOUT TO BE DEPLOYED!!!");
return Plugin_Handled;
}
//When the wave fails
public Action EventWaveFailed(Event Spawn_Event, const char[] Spawn_Name, bool Spawn_Broadcast) {
CPrintToChatAll("{darkviolet}[{forestgreen}CORE{darkviolet}] {white}Wave {red}failed {white}successfully!");
sudo(300);
return Plugin_Handled;
}
//Sacrifice target and grant bonus points
public Action SacrificeClient(int client, int attacker, bool wasBombReset) {
if (attacker <= MaxClients && IsClientInGame(attacker)) {
core.bombReset = false;
core.sacPoints += wasBombReset ? 5 : 1;
core.sacrificedByClient = false;
int steamID = GetSteamAccountID(attacker);
if (!Ass_Database || !steamID) return Plugin_Handled;
char query[256];
CPrintToChatAll(wasBombReset ? "{darkviolet}[{forestgreen}CORE{darkviolet}] {white}Client {red}%N {white}has reset the ass! ({limegreen}+5 pts{white})" : "{darkviolet}[{forestgreen}CORE{darkviolet}] {white}Client {red}%N {white}has sacrificed {blue}%N {white}for the ass! ({limegreen}+1 pt{white})", attacker, client);
Format(query, sizeof(query), wasBombReset ? "UPDATE ass_activity SET bombsreset = bombsreset + 1, bombsresetsession = bombsresetsession + 1 WHERE steamid = %i;" : "UPDATE ass_activity SET sacrifices = sacrifices + 1, sacrificessession = sacrificessession + 1 WHERE steamid = %i;", steamID);
Ass_Database.Query(Database_FastQuery, query);
}
return Plugin_Handled;
}