forked from Mirrors/openclonk
defense: improve goal info and script, king of the hill scenario
parent
b5152e1215
commit
705ab86078
|
@ -38,9 +38,9 @@ protected func InitializePlayer(int plr)
|
|||
if (GetPlayerTeam(plr) != 1)
|
||||
SetPlayerTeam(plr, 1);
|
||||
|
||||
// Move crew to the island.
|
||||
// Move crew to the initial position.
|
||||
var crew = GetCrew(plr);
|
||||
crew->SetPosition(128, 440);
|
||||
crew->SetPosition(120 + Random(16), 440);
|
||||
|
||||
// Set zoom ranges.
|
||||
SetPlayerZoomByViewRange(plr, 1200, nil, PLRZOOM_LimitMax);
|
||||
|
@ -64,6 +64,19 @@ protected func InitializePlayer(int plr)
|
|||
}
|
||||
|
||||
|
||||
/*-- Scenario Control --*/
|
||||
|
||||
public func OnWaveStarted(int wave_nr)
|
||||
{
|
||||
// Fade out enemy ammunition.
|
||||
var enemy_plr = Goal_Defense->GetEnemyPlayer();
|
||||
for (var obj in FindObjects(Find_Func("IsArrow"), Find_NoContainer()))
|
||||
if (obj->GetController() == enemy_plr)
|
||||
obj->AddEffect("IntFadeOut", obj, 100, 1, nil, Rule_ObjectFade);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*-- Waves Control --*/
|
||||
|
||||
public func GetAttackWave(int nr)
|
||||
|
@ -73,7 +86,7 @@ public func GetAttackWave(int nr)
|
|||
return new DefenseEnemy.BreakWave { Duration = 120 };
|
||||
|
||||
// Attack positions.
|
||||
var pos_land = {X = LandscapeWidth(), Y = 760, Exact = true};
|
||||
var pos_land = {X = LandscapeWidth(), Y = 756, Exact = true};
|
||||
var pos_sky = {X = LandscapeWidth() - 100, Y = 0};
|
||||
var pos_above = {X = 200, Y = 0};
|
||||
|
||||
|
@ -138,13 +151,16 @@ public func GetAttackWave(int nr)
|
|||
return wave;
|
||||
}
|
||||
|
||||
// The attackers should go for flagpoles.
|
||||
// The attackers should go for flagpoles, then crewmembers, and then hostile structures.
|
||||
public func GiveRandomAttackTarget(object attacker)
|
||||
{
|
||||
var target = FindObject(Find_Category(C4D_Structure), Find_Func("IsFlagpole"), Find_Hostile(attacker->GetController()), Sort_Random());
|
||||
if (target)
|
||||
return target;
|
||||
target = FindObject(Find_OCF(OCF_CrewMember), Find_Hostile(attacker->GetController()), Sort_Distance());
|
||||
if (target)
|
||||
return target;
|
||||
var target = FindObject(Find_Category(C4D_Structure), Find_Hostile(attacker->GetController()), Sort_Random());
|
||||
if (target)
|
||||
return target;
|
||||
return;
|
||||
|
|
|
@ -3,7 +3,14 @@
|
|||
The players cooperate to defend a base against an enemy for a many attack waves as possible.
|
||||
|
||||
Include the Teams.txt in this object in your defense scenario. Also include a ParameterDefs.txt
|
||||
if you want to have achievements. See Defense.ocf for an example of the file to add.
|
||||
if you want to have achievements. See Defense.ocf for an example of the file to add. Relaunching
|
||||
must be handled by script, for example the relaunch rule, and RelaunchPlayer must not be called,
|
||||
i.e. use OnClonkDeath. The goal can be further controlled by scenario script using the following
|
||||
callbacks:
|
||||
* GetAttackWave(int wave_nr): to specify the enemies of this wave.
|
||||
* GetWaveToAchievement(): to specify the amount of waves needed for bronze, silver and gold stars.
|
||||
* OnWaveStarted(int wave_nr): when a wave has started.
|
||||
* OnWaveCompleted(int wave_nr): when a wave has been completed (i.e. all enemies are eliminated).
|
||||
|
||||
@author Maikel
|
||||
*/
|
||||
|
@ -86,25 +93,30 @@ public func InitializeScriptPlayer(int plr)
|
|||
|
||||
public func RelaunchPlayer(int plr)
|
||||
{
|
||||
// The player has not been relaunched by external scripts and is eliminated.
|
||||
// Move the player into the observer container and let the player spectate.
|
||||
if (GetPlayerType(plr) == C4PT_User)
|
||||
{
|
||||
var crew = CreateObject(Clonk);
|
||||
var crew = CreateObject(Clonk, 0, 0, plr);
|
||||
crew->MakeCrewMember(plr);
|
||||
SetCursor(plr, crew);
|
||||
crew->Enter(observer_container);
|
||||
RemoveArrayValue(plrs_active, GetPlayerID(plr));
|
||||
if (GetLength(plrs_active) == 0)
|
||||
EndRound();
|
||||
return EndRound();
|
||||
// Update the view of the observing players.
|
||||
UpdateOberserverContainer();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public func RemovePlayer(int plr)
|
||||
{
|
||||
// Check completion if a player is removed, the player could have been the last active one.
|
||||
if (GetPlayerType(plr) == C4PT_User)
|
||||
if (RemoveArrayValue(plrs_active, GetPlayerID(plr)))
|
||||
if (GetLength(plrs_active) == 0)
|
||||
EndRound();
|
||||
return EndRound();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -125,6 +137,41 @@ public func EndRound()
|
|||
return;
|
||||
}
|
||||
|
||||
public func UpdateOberserverContainer()
|
||||
{
|
||||
// Get a possible view cursor.
|
||||
var view_cursor;
|
||||
if (GetLength(plrs_active) > 0)
|
||||
{
|
||||
var active_plr = GetPlayerByID(plrs_active[0]);
|
||||
view_cursor = GetCursor(active_plr);
|
||||
}
|
||||
if (view_cursor)
|
||||
{
|
||||
view_cursor->CreateEffect(FxTrackObservation, 100, 0, this);
|
||||
// Set view for existing observers.
|
||||
for (var observer in FindObjects(Find_OCF(OCF_CrewMember), Find_Container(observer_container)))
|
||||
{
|
||||
var observer_plr = observer->GetOwner();
|
||||
SetPlrView(observer_plr, view_cursor);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
local FxTrackObservation = new Effect
|
||||
{
|
||||
Construction = func(object goal)
|
||||
{
|
||||
this.goal = goal;
|
||||
},
|
||||
Destruction = func(int reason)
|
||||
{
|
||||
if (reason == FX_Call_RemoveClear || reason == FX_Call_RemoveDeath)
|
||||
this.goal->UpdateOberserverContainer();
|
||||
}
|
||||
};
|
||||
|
||||
public func IsFulfilled() { return is_fulfilled; }
|
||||
|
||||
|
||||
|
@ -167,6 +214,29 @@ private func GetBestScore(int plr)
|
|||
|
||||
private func GetScoreString() { return Format("Defense_%s_BestScore", GetScenTitle()); }
|
||||
|
||||
private func UpdateBestWave(int new_best_wave)
|
||||
{
|
||||
// Update the best wave for all players.
|
||||
for (var plr in GetPlayers(C4PT_User))
|
||||
SetBestWave(plr, new_best_wave);
|
||||
return;
|
||||
}
|
||||
|
||||
private func SetBestWave(int plr, int new_best_wave)
|
||||
{
|
||||
// Only set if it increases the player's best wave.
|
||||
if (new_best_wave > GetBestWave(plr))
|
||||
SetPlrExtraData(plr, GetWaveString(), new_best_wave);
|
||||
return;
|
||||
}
|
||||
|
||||
private func GetBestWave(int plr)
|
||||
{
|
||||
return GetPlrExtraData(plr, GetWaveString());
|
||||
}
|
||||
|
||||
private func GetWaveString() { return Format("Defense_%s_BestWave", GetScenTitle()); }
|
||||
|
||||
|
||||
/*-- Wave Control --*/
|
||||
|
||||
|
@ -208,6 +278,8 @@ local FxWaveControl = new Effect
|
|||
Target->CreateEffect(Target.FxTrackWave, 100, nil, this.wave_nr, this.wave);
|
||||
// Reset passed time and increase wave number for next wave.
|
||||
this.time_passed = 0;
|
||||
// Do a game call for scenario specific scripts.
|
||||
GameCall("OnWaveStarted", this.wave_nr);
|
||||
}
|
||||
// Increase the time passed in this wave and decrease the pause time.
|
||||
this.time_passed++;
|
||||
|
@ -228,6 +300,8 @@ local FxWaveControl = new Effect
|
|||
GUI_Clock->CreateCountdown(rtime);
|
||||
}
|
||||
}
|
||||
// Do a game call for scenario specific scripts.
|
||||
GameCall("OnWaveCompleted", this.wave_nr);
|
||||
return;
|
||||
},
|
||||
|
||||
|
@ -272,7 +346,22 @@ public func SetRecoveryTime(int to_time)
|
|||
return;
|
||||
}
|
||||
|
||||
public func GetRecoveryTime() { return recovery_time; }
|
||||
public func GetRecoveryTime() { return recovery_time; }
|
||||
|
||||
public func GetEnemyPlayer(int plr)
|
||||
{
|
||||
// Forward to defense goal object.
|
||||
if (this == Goal_Defense)
|
||||
{
|
||||
var goal = FindObject(Find_ID(Goal_Defense));
|
||||
if (goal)
|
||||
return goal->GetEnemyPlayer(plr);
|
||||
return;
|
||||
}
|
||||
if (fx_wave_control)
|
||||
return fx_wave_control->GetEnemy();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*-- Wave Tracking --*/
|
||||
|
@ -331,6 +420,7 @@ public func OnWaveCompleted(int wave_nr)
|
|||
// Increase number of completed waves and update achievements.
|
||||
completed_waves++;
|
||||
CheckAchievement();
|
||||
UpdateBestWave(completed_waves);
|
||||
// Let wave control effect know a wave has been completed.
|
||||
if (fx_wave_control)
|
||||
fx_wave_control->OnWaveCompleted(wave_nr);
|
||||
|
@ -402,7 +492,7 @@ public func CheckAchievement()
|
|||
// Give the players their achievement.
|
||||
if (achievement > 0)
|
||||
GainScenarioAchievement("Done", achievement);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
public func ConvertWaveToAchievement(int wave_nr)
|
||||
|
@ -466,7 +556,8 @@ public func GetDescription(int plr)
|
|||
wave_msg = Format("%s%dx %s\n", wave_msg, enemy.Amount, enemy.Name);
|
||||
}
|
||||
}
|
||||
// Add score.
|
||||
// Add wave and score.
|
||||
wave_msg = Format("%s\n%s", wave_msg, Format("$MsgFinishedWave$", completed_waves, GetBestWave(plr)));
|
||||
wave_msg = Format("%s\n%s", wave_msg, Format("$MsgCurrentScore$", GetScore(), GetBestScore(plr)));
|
||||
return Format("%s\n\n%s", "$Description$", wave_msg);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ MsgEvaluationData=You completed %d waves and scored %d points.
|
|||
MsgCurrentWave=<c ffff00>Jetztige Welle (%d):</c>\n
|
||||
MsgNextWave=<c ffff00>Nächste Welle:</c>\n
|
||||
MsgNoEnemies=Keine Feinde
|
||||
MsgFinishedWave=<c ffff00>Finished wave:</c> %d (your highest wave is %d).
|
||||
MsgCurrentScore=<c ffff00>Current score:</c> %d (your high score is %d).
|
||||
|
||||
MsgScoreboard=Verteidigung: %d Punkte
|
|
@ -11,6 +11,7 @@ MsgEvaluationData=You completed %d waves and scored %d points.
|
|||
MsgCurrentWave=<c ffff00>Current wave (%d):</c>\n
|
||||
MsgNextWave=<c ffff00>Next wave:</c>\n
|
||||
MsgNoEnemies=No enemies
|
||||
MsgFinishedWave=<c ffff00>Finished wave:</c> %d (your highest wave is %d).
|
||||
MsgCurrentScore=<c ffff00>Current score:</c> %d (your high score is %d).
|
||||
|
||||
MsgScoreboard=Defense: %d points
|
Loading…
Reference in New Issue