mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
parent
4056cb80c9
commit
a89ca3e4e5
3 changed files with 236 additions and 8 deletions
|
|
@ -603,4 +603,120 @@ TriggerHelper.SpawnAndTurretAtClasses = function(playerID, classes, templates, c
|
|||
return results;
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes an entity permanently visible to all players by:
|
||||
* - Setting alwaysVisible flag
|
||||
* - Deactivating fogging (no mirages)
|
||||
* - Exploring the surrounding area
|
||||
* - Forcing a visibility update
|
||||
*
|
||||
* @param {number} ent - Entity ID to make permanently visible
|
||||
*/
|
||||
TriggerHelper.MakeEntityPermanentlyVisible = function(ent, exploreRadius = 50)
|
||||
{
|
||||
const cmpVisibility = Engine.QueryInterface(ent, IID_Visibility);
|
||||
if (cmpVisibility)
|
||||
{
|
||||
cmpVisibility.alwaysVisible = true;
|
||||
cmpVisibility.SetActivated(true);
|
||||
}
|
||||
|
||||
const cmpFogging = Engine.QueryInterface(ent, IID_Fogging);
|
||||
if (cmpFogging)
|
||||
cmpFogging.PermanentlyReveal("all");
|
||||
|
||||
const cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||
const cmpPosition = Engine.QueryInterface(ent, IID_Position);
|
||||
if (cmpRangeManager && cmpPosition && cmpPosition.IsInWorld())
|
||||
{
|
||||
const pos = cmpPosition.GetPosition2D();
|
||||
const numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers();
|
||||
for (let i = 1; i < numPlayers; ++i)
|
||||
cmpRangeManager.ExploreCircle(i, pos.x, pos.y, exploreRadius);
|
||||
|
||||
cmpRangeManager.RequestVisibilityUpdate(ent);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends a notification to specific players.
|
||||
*
|
||||
* @param {string} message - The message to display (use markForTranslation)
|
||||
* @param {number[]} players - Array of player IDs to send the notification to
|
||||
* @param {number} duration - Duration in milliseconds
|
||||
* @param {Object} parameters - Translation parameters (optional)
|
||||
*/
|
||||
TriggerHelper.SendNotification = function(message, players, duration = 30000, parameters = {}, translateParameters = [])
|
||||
{
|
||||
const cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
|
||||
if (!cmpGuiInterface)
|
||||
return;
|
||||
|
||||
// Handle case where message is an object from markForPluralTranslation
|
||||
const messageStr = typeof message === "string" ? message : (message.message || String(message));
|
||||
|
||||
// Ensure all parameter values are primitive types
|
||||
const safeParameters = {};
|
||||
for (const key in parameters)
|
||||
{
|
||||
const value = parameters[key];
|
||||
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
||||
safeParameters[key] = value;
|
||||
else
|
||||
safeParameters[key] = String(value);
|
||||
}
|
||||
|
||||
cmpGuiInterface.AddTimeNotification(
|
||||
{
|
||||
"message": messageStr,
|
||||
"players": players,
|
||||
"parameters": safeParameters,
|
||||
"translateMessage": true,
|
||||
"translateParameters": translateParameters
|
||||
},
|
||||
duration
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends a notification to a specific player and a different notification to all other active players.
|
||||
*
|
||||
* @param {number} player - The player ID who gets the 'owner' message
|
||||
* @param {string} ownerMessage - Message for the specified player (use markForTranslation)
|
||||
* @param {string} othersMessage - Message for all other active players (use markForTranslation)
|
||||
* @param {number} duration - Duration in milliseconds
|
||||
* @param {Object} parameters - Translation parameters shared by both messages (optional)
|
||||
* @param {Object} ownerParameters - Additional parameters for the owner message (optional)
|
||||
* @param {Object} othersParameters - Additional parameters for the others message (optional)
|
||||
*/
|
||||
TriggerHelper.SendDualNotification = function(player, ownerMessage, othersMessage, duration = 30000, parameters = {}, ownerParameters = {}, othersParameters = {})
|
||||
{
|
||||
const numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers();
|
||||
|
||||
const others = [];
|
||||
for (let playerID = 1; playerID < numPlayers; ++playerID)
|
||||
{
|
||||
if (playerID == player)
|
||||
continue;
|
||||
const cmpPlayer = QueryPlayerIDInterface(playerID);
|
||||
if (cmpPlayer && cmpPlayer.GetState() == "defeated")
|
||||
continue;
|
||||
others.push(playerID);
|
||||
}
|
||||
|
||||
const mergedOwnerParams = Object.assign({}, parameters, ownerParameters);
|
||||
const mergedOthersParams = Object.assign({}, parameters, othersParameters);
|
||||
|
||||
// Auto-detect translatable parameters (those starting with "_" or named "player")
|
||||
const translateParameters = Object.keys(mergedOthersParams).filter(key => key.startsWith("_") || key == "player");
|
||||
|
||||
TriggerHelper.SendNotification(ownerMessage, [player], duration, mergedOwnerParams, translateParameters);
|
||||
TriggerHelper.SendNotification(othersMessage, others, duration, mergedOthersParams, translateParameters);
|
||||
};
|
||||
|
||||
TriggerHelper.SendWonderNotifications = function(owner, othersMessage, ownerMessage)
|
||||
{
|
||||
TriggerHelper.SendDualNotification(owner, ownerMessage, othersMessage, 30000, { "_player_": owner });
|
||||
};
|
||||
|
||||
Engine.RegisterGlobal("TriggerHelper", TriggerHelper);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,42 @@
|
|||
Trigger.prototype.WonderVictoryEntityRenamed = function(data)
|
||||
{
|
||||
if (this.wonderVictoryMessages[data.entity] && Engine.QueryInterface(data.newentity, IID_Wonder))
|
||||
{
|
||||
// When an entity is renamed, we first create a new entity,
|
||||
// which in case it is a wonder will receive a timer.
|
||||
// However on a rename we want to use the timer from the old entity,
|
||||
// so we need to remove the timer of the new entity.
|
||||
this.WonderVictoryDeleteTimer(data.newentity);
|
||||
if (!Engine.QueryInterface(data.newentity, IID_Wonder))
|
||||
return;
|
||||
|
||||
// Check if wonder victory is enabled
|
||||
const cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
|
||||
if (!cmpEndGameManager)
|
||||
return;
|
||||
|
||||
const victoryConditions = cmpEndGameManager.GetVictoryConditions();
|
||||
if (!victoryConditions || !victoryConditions.includes("wonder"))
|
||||
return;
|
||||
|
||||
// Handle timer transfer (only if old entity had the timer)
|
||||
if (this.wonderVictoryMessages[data.entity])
|
||||
{
|
||||
this.WonderVictoryDeleteTimer(data.newentity);
|
||||
this.wonderVictoryMessages[data.newentity] = this.wonderVictoryMessages[data.entity];
|
||||
delete this.wonderVictoryMessages[data.entity];
|
||||
}
|
||||
|
||||
// Make the completed wonder permanently visible
|
||||
TriggerHelper.MakeEntityPermanentlyVisible(data.newentity, 50);
|
||||
|
||||
// Send "wonder completed" notifications
|
||||
const cmpOwnership = Engine.QueryInterface(data.newentity, IID_Ownership);
|
||||
if (cmpOwnership)
|
||||
{
|
||||
const owner = cmpOwnership.GetOwner();
|
||||
if (owner > 0)
|
||||
{
|
||||
TriggerHelper.SendWonderNotifications(
|
||||
owner,
|
||||
markForTranslation("%(_player_)s has built a Wonder!"),
|
||||
markForTranslation("You have built a Wonder!")
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Trigger.prototype.WonderVictoryOwnershipChanged = function(data)
|
||||
|
|
@ -18,6 +44,15 @@ Trigger.prototype.WonderVictoryOwnershipChanged = function(data)
|
|||
if (!Engine.QueryInterface(data.entity, IID_Wonder))
|
||||
return;
|
||||
|
||||
// Check if wonder victory is enabled
|
||||
const cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
|
||||
if (!cmpEndGameManager)
|
||||
return;
|
||||
|
||||
const victoryConditions = cmpEndGameManager.GetVictoryConditions();
|
||||
if (!victoryConditions || !victoryConditions.includes("wonder"))
|
||||
return;
|
||||
|
||||
this.WonderVictoryDeleteTimer(data.entity);
|
||||
|
||||
if (data.to > 0)
|
||||
|
|
@ -146,11 +181,46 @@ Trigger.prototype.WonderVictorySetWinner = function(playerID)
|
|||
n));
|
||||
};
|
||||
|
||||
Trigger.prototype.WonderStartNotification = function(data)
|
||||
{
|
||||
// Check if wonder victory is enabled in game settings
|
||||
const cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
|
||||
if (!cmpEndGameManager)
|
||||
return;
|
||||
|
||||
// Don't show the wonder foundation if it's not a wonder victory game
|
||||
const victoryConditions = cmpEndGameManager.GetVictoryConditions();
|
||||
if (!victoryConditions || !victoryConditions.includes("wonder"))
|
||||
return;
|
||||
|
||||
const cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
|
||||
if (!cmpTemplateManager)
|
||||
return;
|
||||
|
||||
const template = cmpTemplateManager.GetTemplate(data.template);
|
||||
|
||||
if (!template || !("Wonder" in template))
|
||||
return;
|
||||
|
||||
const owner = TriggerHelper.GetOwner(data.foundation);
|
||||
if (owner <= 0)
|
||||
return;
|
||||
|
||||
TriggerHelper.MakeEntityPermanentlyVisible(data.foundation, 50);
|
||||
|
||||
TriggerHelper.SendWonderNotifications(
|
||||
owner,
|
||||
markForTranslation("%(_player_)s has started building a Wonder."),
|
||||
markForTranslation("You have started building a Wonder.")
|
||||
);
|
||||
};
|
||||
|
||||
{
|
||||
const cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
|
||||
cmpTrigger.RegisterTrigger("OnEntityRenamed", "WonderVictoryEntityRenamed", { "enabled": true });
|
||||
cmpTrigger.RegisterTrigger("OnOwnershipChanged", "WonderVictoryOwnershipChanged", { "enabled": true });
|
||||
cmpTrigger.RegisterTrigger("OnDiplomacyChanged", "WonderVictoryDiplomacyChanged", { "enabled": true });
|
||||
cmpTrigger.RegisterTrigger("OnPlayerWon", "WonderVictoryPlayerWon", { "enabled": true });
|
||||
cmpTrigger.RegisterTrigger("OnConstructionStarted", "WonderStartNotification", { "enabled": true });
|
||||
cmpTrigger.wonderVictoryMessages = {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ Fogging.prototype.Init = function()
|
|||
this.mirages = [];
|
||||
this.miraged = [];
|
||||
this.seen = [];
|
||||
this.revealed = [];
|
||||
|
||||
const numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers();
|
||||
for (let player = 0; player < numPlayers; ++player)
|
||||
|
|
@ -36,6 +37,7 @@ Fogging.prototype.Init = function()
|
|||
this.mirages.push(INVALID_ENTITY);
|
||||
this.miraged.push(false);
|
||||
this.seen.push(false);
|
||||
this.revealed.push(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -169,6 +171,45 @@ Fogging.prototype.WasSeen = function(player)
|
|||
return this.seen[player];
|
||||
};
|
||||
|
||||
/**
|
||||
* Permanently reveal this entity to one or all players.
|
||||
* Destroys existing mirages and optionally deactivates fogging entirely.
|
||||
* @param {number|string} player - Player ID to reveal to, or "all" for all players.
|
||||
*/
|
||||
Fogging.prototype.PermanentlyReveal = function(player = "all")
|
||||
{
|
||||
const cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||
|
||||
// Validate single player case
|
||||
if (player !== "all" && (player < 0 || player >= this.mirages.length))
|
||||
return;
|
||||
|
||||
// Determine which players to reveal
|
||||
const startPlayer = (player === "all") ? 0 : player;
|
||||
const endPlayer = (player === "all") ? this.mirages.length : player + 1;
|
||||
|
||||
// Reveal each player in the range
|
||||
for (let i = startPlayer; i < endPlayer; ++i)
|
||||
{
|
||||
if (this.mirages[i] != INVALID_ENTITY)
|
||||
{
|
||||
Engine.DestroyEntity(this.mirages[i]);
|
||||
this.mirages[i] = INVALID_ENTITY;
|
||||
this.miraged[i] = false;
|
||||
}
|
||||
this.revealed[i] = true;
|
||||
this.seen[i] = true;
|
||||
}
|
||||
|
||||
// Deactivate fogging if revealing to all players
|
||||
if (player === "all")
|
||||
this.activated = false;
|
||||
|
||||
// Request visibility update
|
||||
if (cmpRangeManager)
|
||||
cmpRangeManager.RequestVisibilityUpdate(this.entity);
|
||||
};
|
||||
|
||||
Fogging.prototype.OnOwnershipChanged = function(msg)
|
||||
{
|
||||
// Always activate fogging for non-Gaia entities.
|
||||
|
|
@ -209,7 +250,8 @@ Fogging.prototype.OnVisibilityChanged = function(msg)
|
|||
this.seen[msg.player] = true;
|
||||
}
|
||||
|
||||
if (msg.newVisibility == VIS_FOGGED && this.activated)
|
||||
// Only create a mirage if the player hasn’t been permanently revealed
|
||||
if (msg.newVisibility == VIS_FOGGED && this.activated && !this.revealed[msg.player])
|
||||
this.LoadMirage(msg.player);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue