openclonk/planet/Objects.ocd/Libraries.ocd/Goal.ocd/Script.c

162 lines
3.7 KiB
C

/*--
Goal control
Author: Sven2
Include this to all C4D_Goal objects
Functions to be overloaded:
bool IsFullfilled(); - is the goal fulfilled?
--*/
local mission_password; // mission password to be gained when the goal is fulfilled
// Initialization
func Initialize()
{
// Do not create Library_Goal itself
if (GetID()==Library_Goal)
{
Log("WARNING: Abstract Library_Goal object should not be created; object removed.");
return RemoveObject();
}
// Create timer if it doesn't exist yet
RecheckGoalTimer();
// Done
return _inherited(...);
}
func OnSynchronized()
{
// Create timer if it doesn't exist yet
RecheckGoalTimer();
return _inherited(...);
}
func RecheckGoalTimer()
{
// Create timer if it doesn't exist yet
if (!GetEffect("IntGoalCheck", nil))
{
var timer_interval = 35;
if (GetLeague())
timer_interval = 2; // league has more frequent checks
var num = AddEffect("IntGoalCheck", nil, 1, timer_interval, nil, Library_Goal);
FxIntGoalCheckTimer(nil, num);
}
}
protected func FxIntGoalCheckTimer(object trg, effect, int time)
{
if (!time)
return true;
var curr_goal = effect.curr_goal;
// Check current goal object
if (curr_goal && (curr_goal->GetCategory() & C4D_Goal))
{
curr_goal->NotifyHUD();
if (!curr_goal->~IsFulfilled())
return true;
}
// Current goal is fulfilled/destroyed - check all others
var goal_count = 0;
for (curr_goal in FindObjects(Find_Category(C4D_Goal)))
{
++goal_count;
if (!curr_goal->~IsFulfilled())
{
effect.curr_goal = curr_goal;
curr_goal->NotifyHUD();
return true;
}
}
// No goal object? Kill timer
if (!goal_count)
return FX_Execute_Kill;
// Game over :(
AllGoalsFulfilled();
return FX_Execute_Kill;
}
protected func AllGoalsFulfilled()
{
// Goals fulfilled: Set mission password(s)
for (var goal in FindObjects(Find_Category(C4D_Goal)))
if (goal.mission_password)
GainMissionAccess(goal.mission_password);
// Custom scenario goal evaluation?
if (GameCall("OnGoalsFulfilled")) return true;
// We're done. Play some sound and schedule game over call
Sound("UI::Fanfare", true);
AddEffect("IntGoalDone", nil, 1, 30, nil, Library_Goal);
}
protected func FxIntGoalDoneStop()
{
GameOver();
}
public func NotifyHUD()
{
// create hud objects for all players
for (var i = 0; i < GetPlayerCount(); ++i)
{
var plr = GetPlayerByIndex(i);
var HUD = FindObject(Find_ID(GUI_Controller), Find_Owner(plr));
if (HUD)
HUD->OnGoalUpdate(this);
}
}
protected func InitializePlayer(int plr)
{
var HUD = FindObject(Find_ID(GUI_Controller), Find_Owner(plr));
if (HUD)
HUD->OnGoalUpdate(this);
}
// Set mission password to be gained when all goals are fulfilled
public func SetMissionAccess(string str_password)
{
mission_password = str_password;
}
// Base implementations to be overloaded by goal objects
// Overload: return whether the goal has been fulfilled.
public func IsFulfilled() { return true; }
// Overload: return the current description for this goal.
public func GetDescription(int plr)
{
return this.Description ?? "WARNING: GetDescription(int plr) not overloaded by goal";
}
protected func Activate(plr)
{
if (IsFulfilled())
return(MessageWindow("$MsgGoalFulfilled$", plr));
return MessageWindow(this->GetDescription(plr));
}
// Scenario sacing
func SaveScenarioObject(props)
{
if (!inherited(props, ...)) return false;
if (mission_password) props->AddCall("MissionAccess", this, "SetMissionAccess", Format("%v", mission_password));
return true;
}
/* Graphics storage */
// workaround so goals with different graphics are correctly displayed in the HUD
local goal_custom_graphics;
func SetGraphics(string new_gfx, ...)
{
goal_custom_graphics = new_gfx;
return inherited(new_gfx, ...);
}
func GetGraphics() { return goal_custom_graphics; }