defense: improve goal info and script, king of the hill scenario

install-platforms
Maikel de Vries 2018-01-14 14:42:06 +01:00
parent b5152e1215
commit 705ab86078
4 changed files with 120 additions and 11 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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