Index: binaries/data/config/default.cfg =================================================================== --- binaries/data/config/default.cfg +++ binaries/data/config/default.cfg @@ -484,6 +484,7 @@ [sound.notify] nick = true ; Play a sound when someone mentions your name in the lobby or game gamesetup.join = false ; Play a sound when a new client joins the game setup +session.playerdefeated = false ; Play a sound when a player is defeated [tinygettext] debug = false ; Print error messages each time a translation for an English string is not found. Index: binaries/data/mods/public/audio/interface/alarm/alarm_ally_defeated.xml =================================================================== --- /dev/null +++ binaries/data/mods/public/audio/interface/alarm/alarm_ally_defeated.xml @@ -0,0 +1,15 @@ + + + 1 + owner + 1 + 100 + 1 + 0 + 1 + 1 + 1 + 1 + audio/interface/alarm/ + alarmalert2.ogg + Index: binaries/data/mods/public/audio/interface/alarm/alarm_defeat.xml =================================================================== --- binaries/data/mods/public/audio/interface/alarm/alarm_defeat.xml +++ binaries/data/mods/public/audio/interface/alarm/alarm_defeat.xml @@ -1,13 +0,0 @@ - - - 1 - 100 - 1 - 0 - 1 - 1 - 1 - 1 - audio/interface/alarm/ - alarmdefeat_1.ogg - Index: binaries/data/mods/public/audio/interface/alarm/alarm_defeated.xml =================================================================== --- binaries/data/mods/public/audio/interface/alarm/alarm_defeated.xml +++ binaries/data/mods/public/audio/interface/alarm/alarm_defeated.xml @@ -1,13 +1,15 @@ - - - 1 - 100 - 1 - 0 - 1 - 1 - 1 - 1 - audio/interface/alarm/ - alarmdefeat_1.ogg - + + + 1 + owner + 1 + 100 + 1 + 0 + 1 + 1 + 1 + 1 + audio/interface/alarm/ + alarmalert0.ogg + Index: binaries/data/mods/public/audio/interface/alarm/alarm_enemy_defeated.xml =================================================================== --- /dev/null +++ binaries/data/mods/public/audio/interface/alarm/alarm_enemy_defeated.xml @@ -0,0 +1,15 @@ + + + 1 + owner + 1 + 100 + 1 + 0 + 1 + 1 + 1 + 1 + audio/interface/alarm/ + alarmalert1.ogg + Index: binaries/data/mods/public/gui/options/options.json =================================================================== --- binaries/data/mods/public/gui/options/options.json +++ binaries/data/mods/public/gui/options/options.json @@ -326,6 +326,12 @@ "label": "Game setup - new player notification", "tooltip": "Receive audio notification when a new client joins the game setup.", "config": "sound.notify.gamesetup.join" + }, + { + "type": "boolean", + "label": "Session - player defeated notification", + "tooltip": "Receive audio notification when a player is defeated during the game.", + "config": "sound.notify.session.playerdefeated" } ] }, Index: binaries/data/mods/public/simulation/components/Player.js =================================================================== --- binaries/data/mods/public/simulation/components/Player.js +++ binaries/data/mods/public/simulation/components/Player.js @@ -920,4 +920,21 @@ this.startingTechnologies = techs; }; +Player.prototype.OnGlobalPlayerDefeated = function(msg) +{ + let hasWon = this.state === "won"; + if(!hasWon && Engine.ConfigDB_GetValue("user", "sound.notify.session.playerdefeated") !== "true") + return; + + let cmpSound = Engine.QueryInterface(this.entity, IID_Sound); + if (!cmpSound) + return; + + let cmpSoundManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_SoundManager); + let soundGroup = cmpSound.GetSoundGroup(this.playerID === msg.playerId ? "defeated" : this.IsAlly(msg.playerId) ? "ally_defeated" : hasWon ? "won" : "enemy_defeated"); + if (soundGroup) + cmpSoundManager.PlaySoundGroupForPlayer(soundGroup, this.entity); +}; + + Engine.RegisterComponentType(IID_Player, "Player", Player); Index: binaries/data/mods/public/simulation/templates/special/player/player.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special/player/player.xml +++ binaries/data/mods/public/simulation/templates/special/player/player.xml @@ -89,29 +89,36 @@ 1000 + + + interface/alarm/alarm_defeated.xml + interface/alarm/alarm_ally_defeated.xml + interface/alarm/alarm_enemy_defeated.xml + + - - - Infantry - Worker - FemaleCitizen - Cavalry - Champion - Hero - Siege - Ship - Domestic - Trader - - - House - Economic - Outpost - Military - Fortress - CivCentre - Wonder - + + + Infantry + Worker + FemaleCitizen + Cavalry + Champion + Hero + Siege + Ship + Domestic + Trader + + + House + Economic + Outpost + Military + Fortress + CivCentre + Wonder + Index: source/simulation2/components/CCmpSoundManager.cpp =================================================================== --- source/simulation2/components/CCmpSoundManager.cpp +++ source/simulation2/components/CCmpSoundManager.cpp @@ -91,6 +91,13 @@ g_SoundManager->PlayAsGroup(name, CVector3D(sourcePos), INVALID_ENTITY, false); } + virtual void PlaySoundGroupForPlayer(const std::wstring& name, entity_id_t player) + { + if (!g_SoundManager) + return; + g_SoundManager->PlayAsGroup(name, CVector3D(0.f, 0.f, 0.f), player, true); + } + virtual void StopMusic() { if (!g_SoundManager) Index: source/simulation2/components/ICmpSoundManager.h =================================================================== --- source/simulation2/components/ICmpSoundManager.h +++ source/simulation2/components/ICmpSoundManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -42,6 +42,13 @@ */ virtual void PlaySoundGroupAtPosition(const std::wstring& name, const CFixedVector3D& sourcePos) = 0; + /** + * Start playing audio defined by a sound group file for a player + * @param name VFS path of sound group .xml, relative to audio/ + * @param player the player entity + */ + virtual void PlaySoundGroupForPlayer(const std::wstring& name, entity_id_t player) = 0; + virtual void StopMusic() = 0; DECLARE_INTERFACE_TYPE(SoundManager) Index: source/simulation2/components/ICmpSoundManager.cpp =================================================================== --- source/simulation2/components/ICmpSoundManager.cpp +++ source/simulation2/components/ICmpSoundManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -24,5 +24,6 @@ BEGIN_INTERFACE_WRAPPER(SoundManager) DEFINE_INTERFACE_METHOD_2("PlaySoundGroup", void, ICmpSoundManager, PlaySoundGroup, std::wstring, entity_id_t) DEFINE_INTERFACE_METHOD_2("PlaySoundGroupAtPosition", void, ICmpSoundManager, PlaySoundGroupAtPosition, std::wstring, CFixedVector3D) +DEFINE_INTERFACE_METHOD_2("PlaySoundGroupForPlayer", void, ICmpSoundManager, PlaySoundGroupForPlayer, std::wstring, entity_id_t) DEFINE_INTERFACE_METHOD_0("StopMusic", void, ICmpSoundManager, StopMusic) END_INTERFACE_WRAPPER(SoundManager) Index: source/simulation2/scripting/JSInterface_Simulation.cpp =================================================================== --- source/simulation2/scripting/JSInterface_Simulation.cpp +++ source/simulation2/scripting/JSInterface_Simulation.cpp @@ -33,6 +33,8 @@ #include "simulation2/components/ICmpPosition.h" #include "simulation2/components/ICmpSelectable.h" #include "simulation2/helpers/Selection.h" +#include "ps/scripting/JSInterface_ConfigDB.cpp" + #include #include @@ -145,7 +147,7 @@ CmpPtr cmpPosition(sim->GetSimContext(), entity); if (!cmpPosition || !cmpPosition->IsInWorld()) continue; - + CFixedVector2D halfSize = cmpObstruction->GetStaticSize() / 2; if (halfSize.X.IsZero() || halfSize.Y.IsZero() || std::max(halfSize.X, halfSize.Y) <= fixed::FromInt(2)) continue; @@ -219,4 +221,5 @@ scriptInterface.RegisterFunction("GetEdgesOfStaticObstructionsOnScreenNearTo"); scriptInterface.RegisterFunction, std::string, bool, bool, bool, &PickSimilarPlayerEntities>("PickSimilarPlayerEntities"); scriptInterface.RegisterFunction("SetBoundingBoxDebugOverlay"); + scriptInterface.RegisterFunction("ConfigDB_GetValue"); }