Parkour(some bugfixes and new features).

stable-5.1
Maikel de Vries 2010-01-31 21:31:04 +01:00
parent a74e1d2c06
commit 184b463a39
8 changed files with 349 additions and 202 deletions

View File

@ -1,9 +1,8 @@
[DefCore]
id=MELE
id=Core_Goal_Melee
Version=4,10,0,0
Category=C4D_StaticBack|C4D_Goal
MaxUserSelect=1
Width=1
Height=1
Value=100
Picture=0,0,64,64

View File

@ -50,7 +50,7 @@ public func IsFulfilled()
return true;
}
protected func Activate(int byplr)
public func Activate(int byplr)
{
// Count enemy players.
var hostile_count;
@ -71,6 +71,11 @@ protected func Activate(int byplr)
return;
}
public func GetShortDescription(int plr)
{
return ""; // TODO
}
func Definition(def) {
SetProperty("Name", "$Name$", def);
}

View File

@ -20,42 +20,42 @@ static const RACE_CP_Check = 8;
static const RACE_CP_Ordered = 16;
static const RACE_CP_Bonus = 32;
public func SetCPMode(int iMode)
public func SetCPMode(int mode)
{
if (iMode & RACE_CP_Start) // Start always occurs alone.
iMode = RACE_CP_Start;
if (iMode & RACE_CP_Finish) // Start always occurs alone.
iMode = RACE_CP_Finish;
if (iMode & RACE_CP_Ordered) // Ordered checkpoints must have RACE_CP_Check.
if (mode & RACE_CP_Start) // Start always occurs alone.
mode = RACE_CP_Start;
if (mode & RACE_CP_Finish) // Start always occurs alone.
mode = RACE_CP_Finish;
if (mode & RACE_CP_Ordered) // Ordered checkpoints must have RACE_CP_Check.
{
iMode = iMode | RACE_CP_Check;
mode = mode | RACE_CP_Check;
// Set CP number.
SetCPNumber(ObjectCount(Find_ID(GetID()), Find_Func("GetCPNumber")) + 1);
}
CP_Mode = iMode;
CP_Mode = mode;
UpdateGraphics();
return;
}
public func GetCPMode() { return CP_Mode; }
public func FindCPMode(int iMode) { return CP_Mode & iMode; }
public func FindCPMode(int mode) { return CP_Mode & mode; }
/*-- Checkpoint controller --*/
local CP_Con;
public func SetCPController(object pCon)
public func SetCPController(object con)
{
CP_Con = pCon;
CP_Con = con;
return;
}
/*-- Checkpoint number --*/
local CP_Num;
public func SetCPNumber(int iNum)
public func SetCPNumber(int num)
{
CP_Num = iNum;
CP_Num = num;
return;
}
@ -78,23 +78,24 @@ protected func Initialize()
/*-- Checkpoint status --*/
public func ClearedByPlr(int iPlr)
public func ClearedByPlr(int plr)
{
return aDoneByPlr[iPlr];
var plrid = GetPlayerID(plr);
return aDoneByPlr[plrid];
}
public func ClearedByTeam(int iTeam)
public func ClearedByTeam(int team)
{
return aDoneByTeam[iTeam];
return aDoneByTeam[team];
}
public func IsActiveForPlr(int iPlr)
public func IsActiveForPlr(int plr)
{
if (CP_Mode & RACE_CP_Finish) // Check all checkpoints.
{
for (var cp in FindObjects(Find_ID(GetID())))
if (cp->GetCPMode() & RACE_CP_Check)
if (!cp->ClearedByPlr(iPlr))
if (!cp->ClearedByPlr(plr))
return false;
return true;
}
@ -104,19 +105,19 @@ public func IsActiveForPlr(int iPlr)
return true;
for (var cp in FindObjects(Find_ID(GetID()), Find_Func("GetCPNumber")))
if (cp->GetCPNumber() + 1 == GetCPNumber())
if (cp->ClearedByPlr(iPlr))
if (cp->ClearedByPlr(plr))
return true;
return false;
}
return true;
}
public func IsActiveForTeam(int iTeam)
public func IsActiveForTeam(int team)
{
if (!iTeam)
if (!team)
return false;
for (var i = 0; i < GetPlayerCount(); i++)
if (GetPlayerTeam(GetPlayerByIndex(i)) == iTeam)
if (GetPlayerTeam(GetPlayerByIndex(i)) == team)
if (IsActiveForPlr(GetPlayerByIndex(i)))
return true;
return false;
@ -134,50 +135,50 @@ protected func CheckForClonks()
{
// Loop through all clonks inside the checkpoint.
for (var pClonk in FindObjects(Find_OCF(OCF_CrewMember), Find_Distance(20)))
{
var iPlr = pClonk->GetOwner();
var iTeam = GetPlayerTeam(iPlr);
// Check whether this CP is already activated for iPlr or its team.
if (!IsActiveForPlr(iPlr))
if (!IsActiveForTeam(iTeam))
continue;
{
var plr = pClonk->GetOwner();
var team = GetPlayerTeam(plr);
var plrid = GetPlayerID(plr);
// Check whether this CP is already activated for player or its team.
if (!IsActiveForPlr(plr) && !IsActiveForTeam(team))
continue;
// Check respawn status.
if (CP_Mode & RACE_CP_Respawn)
if (CP_Con)
CP_Con->SetPlrRespawnCP(iPlr, this); // Notify race goal.
CP_Con->SetPlrRespawnCP(plr, this); // Notify race goal.
// If already done by player -> continue.
if (aDoneByPlr[iPlr])
if (aDoneByPlr[plrid])
continue;
// Check checkpoint status.
if (CP_Mode & RACE_CP_Check)
{
aDoneByPlr[iPlr] = true;
Sound("Cleared", false, nil, iPlr);
if (!iTeam)
aDoneByPlr[plrid] = true;
Sound("Cleared", false, nil, plr);
if (!team)
if (CP_Con)
CP_Con->AddPlrClearedCP(iPlr); // Notify race goal.
if (iTeam && !aDoneByTeam[iTeam])
CP_Con->AddPlrClearedCP(plr); // Notify race goal.
if (team && !aDoneByTeam[team])
{
aDoneByTeam[iTeam] = true;
aDoneByTeam[team] = true;
if (CP_Con)
CP_Con->AddPlrClearedCP(iPlr); // Notify race goal.
CP_Con->AddPlrClearedCP(plr); // Notify race goal.
}
UpdateColor();
}
// Check finish status.
if (CP_Mode & RACE_CP_Finish)
{
Sound("Cleared", false, nil, iPlr);
aDoneByPlr[iPlr] = true;
if (iTeam)
aDoneByTeam[iTeam] = true;
Sound("Cleared", false, nil, plr);
aDoneByPlr[plrid] = true;
if (team)
aDoneByTeam[team] = true;
if (CP_Con)
CP_Con->PlayerHasReachedFinish(iPlr); // Notify race goal.
CP_Con->PlrReachedFinishCP(plr); // Notify race goal.
UpdateColor();
}
// Check bonus.
if (CP_Mode & RACE_CP_Bonus)
GameCall("GivePlrBonus", iPlr, this);
GameCall("GivePlrBonus", plr, this);
}
return;
}
@ -208,11 +209,18 @@ protected func UpdateGraphics()
SetGraphics("Check", GetID(), 3, GFXOV_MODE_Base);
SetObjDrawTransform(1000, 0, 6000, 0, 1000, -3000, 3);
}
// Ordered.
// Ordered, display numbers up to 99.
if (CP_Mode & RACE_CP_Ordered)
{
SetGraphics(Format("%d", GetCPNumber()), NUMB, 4, GFXOV_MODE_Base);
SetObjDrawTransform(200, 0, 0, 0, 200, 9000, 4);
if (GetCPNumber() >= 10)
{
SetGraphics(Format("%d", GetCPNumber()/10), NUMB, 5, GFXOV_MODE_Base);
SetObjDrawTransform(200, 0, -2500, 0, 200, 9000, 5);
SetClrModulation(RGBa(255, 255, 255, 128) , 5);
}
SetGraphics(Format("%d", GetCPNumber()%10), NUMB, 4, GFXOV_MODE_Base);
SetObjDrawTransform(200, 0, 2500, 0, 200, 9000, 4);
SetClrModulation(RGBa(255, 255, 255, 128) , 4);
}
return;
}
@ -230,18 +238,20 @@ protected func UpdateColor()
for (var i = 0; i < GetLength(aDoneByPlr); i++)
{
if (aDoneByPlr[i])
{
SetGraphics("Ring8", GetID(), 5 + i, GFXOV_MODE_Base);
SetClrModulation(GetPlrColor(i), 5 + i);
{ // Does not work with TeamColors=1.
SetGraphics("Ring8", GetID(), 6 + i, GFXOV_MODE_Base);
SetClrModulation(GetPlrColor(GetPlayerByIndex(ringsec)), 6 + i); //WRONG.
var angle = ringsec * 45;
var s = Sin(angle, 1000), c = Cos(angle, 1000);
SetObjDrawTransform(c, s, 0, -s, c, 0, 5 + i);
SetObjDrawTransform(c, s, 0, -s, c, 0, 6 + i);
ringsec++;
}
}
return;
}
/*-- Proplist --*/
func Definition(def) {
SetProperty("Name", "$Name$", def);
}

View File

@ -8,17 +8,26 @@
* Check: On/Off - The clonk must pass through these checkpoints before being able to finish.
* Ordered: On/Off - The checkpoints mussed be passed in the order specified.
* The start and finish are also checkpoints.
ToDo: Scoreboard, Teams, Color update CP, relative distance to next CP in scoreboard.
ToDo:
* Scoreboard with teams -> commented away, since bugs.
* Update CP Graphics.
* Relative distance to next CP in scoreboard -> done.
* Arrow showing direction to next CP -> partially done.
* maybe update array access to plrID -> done.
* Add evaluation data.
*/
#include GOAL
local fFinished; // Whether the goal has been reached by some player.
local aCheckpoints; // List of checkpoints.
local nrCheckpoints; // Nr. of checkpoints.
local nrCheckpoints; // Number of checkpoints.
local aRespawnCP; // List of last reached respawn CP per player.
local aPlrCP; // Number of checkpoints the player completed.
local aTeamCP; // Number of checkpoints the team completed.
local szBestTimeString; // String for best time storage in player file.
/*-- General --*/
protected func Initialize()
{
@ -28,44 +37,48 @@ protected func Initialize()
aRespawnCP = [];
aPlrCP = [];
aTeamCP = [];
// Best time tracking.
szBestTimeString = Format("PARK_%s_BestTime", GetScenTitle());
AddEffect("IntBestTime", this, 100, 1, this);
// Activate restart rule, if there isn't any.
if (!FindObject(Find_ID(Core_Rule_Restart)))
CreateObject(Core_Rule_Restart, 0, 0, NO_OWNER);
// Scoreboard distance display.
InitScoreboard();
AddEffect("IntSBDistance", this, 100, 35, this);
return _inherited(...);
}
/*-- Checkpoint creation --*/
public func SetStartpoint(int iX, int iY)
public func SetStartpoint(int x, int y)
{
var cp = CreateObject(Core_Goal_Checkpoint, iX, iY, NO_OWNER);
cp->SetPosition(iX, iY);
var cp = CreateObject(Core_Goal_Checkpoint, x, y, NO_OWNER);
cp->SetPosition(x, y);
cp->SetCPMode(RACE_CP_Start);
cp->SetCPController(this);
aCheckpoints[0] = cp;
return;
}
public func SetFinishpoint(int iX, int iY)
public func SetFinishpoint(int x, int y)
{
var cp = CreateObject(Core_Goal_Checkpoint, iX, iY, NO_OWNER);
cp->SetPosition(iX, iY);
var cp = CreateObject(Core_Goal_Checkpoint, x, y, NO_OWNER);
cp->SetPosition(x, y);
cp->SetCPMode(RACE_CP_Finish);
cp->SetCPController(this);
aCheckpoints[nrCheckpoints + 1] = cp;
return;
}
public func AddCheckpoint(int iX, int iY, int iMode)
public func AddCheckpoint(int x, int y, int mode)
{
var cp = CreateObject(Core_Goal_Checkpoint, iX, iY, NO_OWNER);
cp->SetPosition(iX, iY);
cp->SetCPMode(iMode);
var cp = CreateObject(Core_Goal_Checkpoint, x, y, NO_OWNER);
cp->SetPosition(x, y);
cp->SetCPMode(mode);
cp->SetCPController(this);
if (iMode & RACE_CP_Check || iMode & RACE_CP_Ordered)
if (mode & RACE_CP_Check || mode & RACE_CP_Ordered)
{
nrCheckpoints++;
aCheckpoints[nrCheckpoints + 1] = aCheckpoints[nrCheckpoints]; // Finish 1 place further.
@ -76,53 +89,58 @@ public func AddCheckpoint(int iX, int iY, int iMode)
/*-- Checkpoint interaction --*/
// Called from a finish CP to indicate that iPlr has reached it.
public func PlayerHasReachedFinish(int iPlr)
// Called from a finish CP to indicate that plr has reached it.
public func PlrReachedFinishCP(int plr)
{
aPlrCP[iPlr]++;
if (GetPlayerTeam(iPlr))
aTeamCP[GetPlayerTeam(iPlr)]++;
UpdateScoreboard(iPlr);
EliminatePlayers(iPlr);
var plrid = GetPlayerID(plr);
aPlrCP[plrid]++;
if (GetPlayerTeam(plr))
aTeamCP[GetPlayerTeam(plr)]++;
UpdateScoreboard(plr);
DoBestTime(plr);
SetEvalData(plr);
EliminatePlayers(plr);
fFinished = true;
return;
}
// Called from a respawn CP to indicate that iPlr has reached it.
public func SetPlrRespawnCP(int iPlr, object cp)
// Called from a respawn CP to indicate that plr has reached it.
public func SetPlrRespawnCP(int plr, object cp)
{
if (aRespawnCP[iPlr] == cp)
if (aRespawnCP[plr] == cp)
return;
aRespawnCP[iPlr] = cp;
PlrMessage(Translate("MsgNewRespawn"), iPlr);
aRespawnCP[plr] = cp;
PlrMessage(Translate("MsgNewRespawn"), plr);
return;
}
// Called from a check CP to indicate that iPlr has cleared it.
public func AddPlrClearedCP(int iPlr)
// Called from a check CP to indicate that plr has cleared it.
public func AddPlrClearedCP(int plr)
{
aPlrCP[iPlr]++;
if (GetPlayerTeam(iPlr))
aTeamCP[GetPlayerTeam(iPlr)]++;
UpdateScoreboard(iPlr);
var plrid = GetPlayerID(plr);
var team = GetPlayerTeam(plr);
aPlrCP[plrid]++;
if (team)
aTeamCP[team]++;
UpdateScoreboard(plr);
return;
}
/*-- Goal checking --*/
/*-- Goal interface --*/
// Eliminate all players apart from iWinner and his team.
private func EliminatePlayers(int iWinner)
// Eliminates all players apart from the winner and his team.
private func EliminatePlayers(int winner)
{
var iWinTeam = GetPlayerTeam(iWinner);
var winteam = GetPlayerTeam(winner);
for (var i = 0; i < GetPlayerCount(); i++)
{
var iPlr = GetPlayerByIndex(i);
var iTeam = GetPlayerTeam(iPlr);
if (iPlr == iWinner) // The winner self.
var plr = GetPlayerByIndex(i);
var team = GetPlayerTeam(plr);
if (plr == winner) // The winner self.
continue;
if (iTeam && iTeam == iWinTeam) // In the same team as the winner.
if (team && team == winteam) // In the same team as the winner.
continue;
EliminatePlayer(iPlr);
EliminatePlayer(plr);
}
return;
}
@ -132,139 +150,131 @@ public func IsFulfilled()
return fFinished;
}
public func Activate(int iPlr)
public func Activate(int plr)
{
var iTeam = GetPlayerTeam(iPlr);
var szMessage = "";
var team = GetPlayerTeam(plr);
var msg;
if (fFinished)
{
if (iTeam)
if (team)
{
if (IsWinner(iPlr))
szMessage = Format(Translate("MsgRaceWonTeam"));
if (IsWinner(plr))
msg = Format(Translate("MsgRaceWonTeam"));
else
szMessage = Format(Translate("MsgRaceLostTeam"));
msg = Format(Translate("MsgRaceLostTeam"));
}
else
{
if (IsWinner(iPlr))
szMessage = Format(Translate("MsgRaceWon"));
if (IsWinner(plr))
msg = Format(Translate("MsgRaceWon"));
else
szMessage = Format(Translate("MsgRaceLost"));
msg = Format(Translate("MsgRaceLost"));
}
}
else
szMessage = Format(Translate("MsgRace"), nrCheckpoints + 1);
msg = Format(Translate("MsgRace"), nrCheckpoints + 1);
// Show goal message.
MessageWindow(szMessage, iPlr);
MessageWindow(msg, plr);
return;
}
private func IsWinner(int iPlr)
public func GetShortDescription(int plr)
{
var iTeam = GetPlayerTeam(iPlr);
return Translate("MsgDesc");
}
private func IsWinner(int plr)
{
var team = GetPlayerTeam(plr);
var finish = FindObject(Find_ID(Core_Goal_Checkpoint), Find_Func("FindCPMode", RACE_CP_Finish));
if (!finish)
return false;
if (iTeam)
if (team)
{
if (finish->ClearedByTeam(iTeam))
if (finish->ClearedByTeam(team))
return true;
}
else
{
if (finish->ClearedByPlr(iPlr))
if (finish->ClearedByPlr(plr))
return true;
}
return false;
}
/*-- Player section --*/
protected func InitializePlayer(int iPlr, int iX, int iY, object pBase, int iTeam)
protected func InitializePlayer(int plr, int x, int y, object base, int team)
{
// If the race is already finished, then immediately eliminate player.
if (fFinished)
return EliminatePlayer(iPlr);
return EliminatePlayer(plr);
// Remove all hostilities.
for (var i = 0; i < GetPlayerCount(); i++)
{
SetHostility(iPlr, GetPlayerByIndex(i), 0, 1);
SetHostility(GetPlayerByIndex(i), iPlr, 0, 1);
SetHostility(plr, GetPlayerByIndex(i), false, true);
SetHostility(GetPlayerByIndex(i), plr, false, true);
}
// Init Respawn CP to start CP.
aRespawnCP[iPlr] = aCheckpoints[0];
aPlrCP[iPlr] = 0;
if (iTeam)
if (!aPlrCP[iTeam])
aPlrCP[iTeam] = 0;
UpdateScoreboard(iPlr);
DoScoreboardShow(1, iPlr + 1);
JoinPlayer(iPlr);
var plrid = GetPlayerID(plr);
aRespawnCP[plr] = aCheckpoints[0];
aPlrCP[plrid] = 0;
if (team)
if (!aTeamCP[team])
aTeamCP[team] = 0;
// Scoreboard.
InitScoreboard();
UpdateScoreboard(plr);
DoScoreboardShow(1, plr + 1);
JoinPlayer(plr);
// Scenario script callback.
GameCall("PlrHasRespawned", iPlr, aRespawnCP[iPlr]);
GameCall("PlrHasRespawned", plr, aRespawnCP[plr]);
return;
}
protected func OnClonkDeath(object clonk)
protected func RelaunchPlayer(int plr)
{
var iPlr = clonk->GetOwner();
var nclonk = CreateObject(CLNK, 0, 0, iPlr);
nclonk->MakeCrewMember(iPlr);
nclonk->GrabObjectInfo(clonk);
SetCursor(iPlr, nclonk);
SelectCrew(iPlr, nclonk, true);
JoinPlayer(iPlr);
var clonk = CreateObject(CLNK, 0, 0, plr);
clonk->MakeCrewMember(plr);
SetCursor(plr, clonk);
SelectCrew(plr, clonk, true);
JoinPlayer(plr);
// Scenario script callback.
GameCall("PlrHasRespawned", iPlr, aRespawnCP[iPlr]);
GameCall("PlrHasRespawned", plr, aRespawnCP[plr]);
// Log message.
Log(RndRespawnMsg(), GetPlayerName(iPlr));
}
/*
protected func RelaunchPlayer(int iPlr)
{
var clonk = CreateObject(CLNK, 0, 0, iPlr);
clonk->MakeCrewMember(iPlr);
SetCursor(iPlr, clonk);
SelectCrew(iPlr, clonk, true);
JoinPlayer(iPlr);
// Scenario script callback.
GameCall("PlrHasRespawned", iPlr, aRespawnCP[iPlr]);
// Log message.
Log(RndRespawnMsg(), GetPlayerName(iPlr));
Log(RndRespawnMsg(), GetPlayerName(plr));
return;
}
*/
private func RndRespawnMsg()
{
return Translate(Format("MsgRespawn%d", Random(4)));
}
protected func JoinPlayer(int iPlr)
protected func JoinPlayer(int plr)
{
var clonk = GetCrew(iPlr);
var clonk = GetCrew(plr);
clonk->DoEnergy(100000);
var x, y;
FindRespawnPos(iPlr, x, y);
FindRespawnPos(plr, x, y);
clonk->SetPosition(x, y);
AddEffect("IntDirNextCP", clonk, 100, 10, this);
return;
}
private func FindRespawnPos(int iPlr, int &iX, int &iY)
private func FindRespawnPos(int plr, int &x, int &y)
{
iX = aRespawnCP[iPlr]->GetX();
iY = aRespawnCP[iPlr]->GetY();
x = aRespawnCP[plr]->GetX();
y = aRespawnCP[plr]->GetY();
return;
}
protected func RemovePlayer(int iPlr)
protected func RemovePlayer(int plr)
{
// TODO
if (!fFinished)
AddEvalData(plr);
return;
}
@ -279,40 +289,64 @@ protected func FxIntSBDistanceTimer()
static const SBRD_Checkpoints = 0;
static const SBRD_Distance = 1;
static const SBRD_BestTime = 2;
private func UpdateScoreboard(int iPlr)
private func InitScoreboard()
{
// TODO
var szCaption = Format("Race over %d checkpoints", nrCheckpoints + 1);
SetScoreboardData(SBRD_Caption, SBRD_Caption, szCaption, SBRD_Caption);
SetScoreboardData(SBRD_Caption, SBRD_Checkpoints, Format("{{%i}}", Core_Goal_Checkpoint), SBRD_Caption);
SetScoreboardData(SBRD_Caption, SBRD_Distance, Format("->{{%i}}", Core_Goal_Checkpoint), SBRD_Caption);
SetScoreboardData(iPlr, SBRD_Caption, GetTaggedPlayerName(iPlr), SBRD_Caption);
SetScoreboardData(iPlr, SBRD_Checkpoints, Format("%d", aPlrCP[iPlr]), aPlrCP[iPlr]);
SetScoreboardData(iPlr, SBRD_Distance, Format("%d%", GetDistToCP(iPlr)), GetDistToCP(iPlr));
if (nrCheckpoints > 0)
var caption = Format(Translate("MsgCaptionX"), nrCheckpoints + 1);
else
var caption = Translate("MsgCaptionNone");
// The above row.
SetScoreboardData(SBRD_Caption, SBRD_Caption, caption, SBRD_Caption);
SetScoreboardData(SBRD_Caption, SBRD_Checkpoints, Format("{{%i}}", Core_Goal_Checkpoint), SBRD_Caption);
SetScoreboardData(SBRD_Caption, SBRD_Distance, Format("->{{%i}}", Core_Goal_Checkpoint), SBRD_Caption);
SetScoreboardData(SBRD_Caption, SBRD_BestTime, "T", SBRD_Caption);
return;
}
// Returns the number of players in a team
private func GetTeamPlrCount(int iTeam)
private func UpdateScoreboard(int plr)
{
var cnt = 0;
for(var i = 0; i < GetPlayerCount(); i++)
if(GetPlayerTeam(GetPlayerByIndex(i)) == iTeam)
cnt++;
return cnt;
var plrid = GetPlayerID(plr);
// The player name.
SetScoreboardData(plrid, SBRD_Caption, GetTaggedPlayerName(plr), SBRD_Caption);
// The player scores.
SetScoreboardData(plrid, SBRD_Checkpoints, Format("%d", aPlrCP[plrid]), aPlrCP[plrid]);
SetScoreboardData(plrid, SBRD_Distance, Format("%d%", GetDistToCP(plr)), GetDistToCP(plr));
SetScoreboardData(plrid, SBRD_BestTime, TimeToString(GetPlrExtraData(plr, szBestTimeString)), SBRD_Caption);
// Sort.
SortScoreboard(SBRD_Distance, false);
SortScoreboard(SBRD_Checkpoints, true);
return;
}
// Only works for ordered CPs
private func GetDistToCP(int iPlr)
/*-- Direction & distance indication --*/
// Returns the last cleared CP for plr.
private func FindLastCP(int plr)
{
// Get last finished ordered CP.
var lastcp;
for (var cp in FindObjects(Find_ID(Core_Goal_Checkpoint), Find_Func("FindCPMode", RACE_CP_Ordered), Find_Func("ClearedByPlr", iPlr)))
for (var cp in FindObjects(Find_ID(Core_Goal_Checkpoint), Find_Func("FindCPMode", RACE_CP_Ordered), Find_Func("ClearedByPlr", plr)))
if (!lastcp || lastcp->~GetCPNumber() < cp->~GetCPNumber())
lastcp = cp;
if (!lastcp)
lastcp = FindObject(Find_ID(Core_Goal_Checkpoint), Find_Func("FindCPMode", RACE_CP_Start));
return lastcp;
}
// Returns the next CP for plr.
private func FindNextCP(int plr)
{
var nextcp;
return;
}
// Only works for ordered CPs
private func GetDistToCP(int plr)
{
// Get last finished ordered CP.
var lastcp = FindLastCP(plr);
if (!lastcp)
return 0;
// Get next ordered CP.
@ -324,21 +358,20 @@ private func GetDistToCP(int iPlr)
nextcp = FindObject(Find_ID(Core_Goal_Checkpoint), Find_Func("FindCPMode", RACE_CP_Finish));
if (!nextcp)
return 0;
var dist = ObjectDistance(GetCrew(iPlr), nextcp);
var dist = ObjectDistance(GetCrew(plr), nextcp);
dist = (100 * dist) / ObjectDistance(lastcp, nextcp);
dist = BoundBy(dist, 0, 100);
return dist;
}
/*-- Direction indication --*/
// Effect for direction indication for the clonk.
protected func FxIntDirNextCPTimer(object pTarget, int iEffectNumber, int iEffectTime)
{
var plr = pTarget->GetOwner();
// Find nearest CP.
var nextcp;
for (var cp in FindObjects(Find_ID(Core_Goal_Checkpoint), Find_Func("FindCPMode", RACE_CP_Check | RACE_CP_Finish), Sort_Distance(pTarget->GetX()-GetX(), pTarget->GetY()-GetY())))
if (!cp->ClearedByPlr(plr) && (cp->IsActiveForPlr(plr) || cp->IsActiveForPlr(GetPlayerTeam(plr))))
if (!cp->ClearedByPlr(plr) && (cp->IsActiveForPlr(plr) || cp->IsActiveForTeam(GetPlayerTeam(plr))))
{
nextcp = cp;
break;
@ -347,11 +380,83 @@ protected func FxIntDirNextCPTimer(object pTarget, int iEffectNumber, int iEffec
return;
// Calculate angle.
var angle = Angle(pTarget->GetX(), pTarget->GetY(), nextcp->GetX(), nextcp->GetY());
// Effect.
// Effect, should be replaced with an arrow.
CreateParticle("DebugReticle", pTarget->GetX()+Sin(angle, 20)-GetX(), pTarget->GetY()-Cos(angle,20)-GetY(), 0, 0, 30, RGB(255,0,0));
return FX_OK;
}
/*-- Time tracker --*/
private func DoBestTime(int plr)
{
var effect = GetEffect("IntBestTime", this);
var time = EffectVar(0, this, effect);
var rectime = GetPlrExtraData(plr, szBestTimeString);
if (time != 0 && (!rectime || time < rectime))
{
SetPlrExtraData(plr, szBestTimeString, time);
Log(Format(Translate("MsgBestTime"), GetPlayerName(plr), TimeToString(time)));
}
return;
}
// Starts at goal initialization, should be equivalent to gamestart.
protected func FxIntBestTimeTimer(object pTarget, int iEffectNumber, int iEffectTime)
{
EffectVar(0, pTarget, iEffectNumber) = iEffectTime;
return FX_OK;
}
// Returns a best time string.
private func TimeToString(int time)
{
if (!time) // No time.
return "N/A";
if (time > 36*60*60) // Longer than an hour.
return Format("%d:%.2d:%.2d.%.1d", (time/60/60/36)%24, (time/60/36)%60, (time/36)%60, (10*time/36)%10);
if (time > 36*60) // Longer than a minute.
return Format("%d:%.2d.%.1d", (time/60/36)%60, (time/36)%60, (10*time/36)%10);
else // Only seconds.
return Format("%d.%.1d", (time/36)%60, (10*time/36)%10);
}
/*-- Evaluation data --*/
private func SetEvalData(int winner)
{
var winteam = GetPlayerTeam(winner);
var effect = GetEffect("IntBestTime", this);
var time = EffectVar(0, this, effect);
var msg;
// General data.
if (winteam)
msg = Format(Translate("MsgEvalTeamWon"), GetTeamName(winteam), TimeToString(time));
else
msg = Format(Translate("MsgEvalPlrWon"), GetPlayerName(winner), TimeToString(time));
AddEvaluationData(msg, 0);
// Individual data.
for (var i = 0; i < GetPlayerCount(); i++)
AddEvalData(GetPlayerByIndex(i));
// Obviously get rid of settlement score.*/
HideSettlementScoreInEvaluation(true);
return;
}
private func AddEvalData(int plr)
{
var plrid = GetPlayerID(plr);
var cps = aPlrCP[plrid];
var msg;
if (cps == nrCheckpoints)
msg = Translate("MsgEvalPlayerAll");
else
msg = Format(Translate("MsgEvalPlayerX"), cps);
AddEvaluationData(msg, plrid);
return;
}
/*-- Proplist --*/
func Definition(def) {
SetProperty("Name", "$Name$", def);
}
}

View File

@ -1,6 +1,6 @@
NameRace=Wettrennen
Name=Parkour
#Race
#Goal window
MsgRace=This is race over %d checkpoints, check the scoreboard for the number of completed checkpoints per team/player.
MsgRaceWon=Congratulations, you have won the race!
MsgRaceWonTeam=Congratulations, your team has won the race!
@ -8,8 +8,24 @@ MsgRaceLost=You have lost the race.
MsgRaceLostTeam=Your team has lost the race.
#Respawn
MsgRespawn0=%s tries it again.
MsgRespawn1=%s is dead.
MsgRespawn0=%s tries again.
MsgRespawn1=%s has died.
MsgRespawn2=Haha, %s!
MsgRespawn3=We're mourning %s.
MsgNewRespawn=You'll now respawn here.
MsgNewRespawn=You'll now respawn here.
#Description
MsgDesc=You are in a race.
#Scoreboard
MsgCaptionX=Race over %d checkpoints.
MsgCaptionNone=Race without checkpoints.
#Best time
MsgBestTime=%s has set a new personal best time of %s.
#Evaluation data
MsgEvalPlrWon=%s has won the parkour in %s.
MsgEvalTeamWon=The team %s has won the parkour in %s.
MsgEvalPlayerX=You have cleared %d checkpoints.
MsgEvalPlayerAll=You have cleared all checkpoints.

View File

@ -1,6 +1,6 @@
Name=Race
Name=Parkour
#Race
#Goal window
MsgRace=This is race over %d checkpoints, check the scoreboard for the number of completed checkpoints per team/player.
MsgRaceWon=Congratulations, you have won the race!
MsgRaceWonTeam=Congratulations, your team has won the race!
@ -8,8 +8,24 @@ MsgRaceLost=You have lost the race.
MsgRaceLostTeam=Your team has lost the race.
#Respawn
MsgRespawn0=%s tries it again.
MsgRespawn1=%s is dead.
MsgRespawn0=%s tries again.
MsgRespawn1=%s has died.
MsgRespawn2=Haha, %s!
MsgRespawn3=We're mourning %s.
MsgNewRespawn=You'll now respawn here.
#Description
MsgDesc=You are in a race.
#Scoreboard
MsgCaptionX=Race over %d checkpoints.
MsgCaptionNone=Race without checkpoints.
#Best time
MsgBestTime=%s has set a new personal best time of %s.
#Evaluation data
MsgEvalPlrWon=%s has won the parkour in %s.
MsgEvalTeamWon=The team %s has won the parkour in %s.
MsgEvalPlayerX=You have cleared %d checkpoints.
MsgEvalPlayerAll=You have cleared all checkpoints.

View File

@ -1,6 +1,6 @@
[Head]
Icon=26
Title=TheCavern
Title=Cavern
Version=4,10,0,0
MaxPlayer=12
@ -8,25 +8,21 @@ MaxPlayer=12
Definition1=Objects.c4d
[Player1]
Wealth=50,0,0,250
Crew=CLNK=1
[Player2]
Wealth=50,0,0,250
Crew=CLNK=1
[Player3]
Wealth=50,0,0,250
Crew=CLNK=1
[Player4]
Wealth=50,0,0,250
Crew=CLNK=1
[Landscape]
InEarth=ROCK=1;GOLD=1;DYNA=3;LOAM=3
InEarthLevel=80,0,0,100
Sky=Clouds2
Sky=Clouds1
MapWidth=100,0,64,10000
MapHeight=250,0,40,10000
SkyScrollMode=2

View File

@ -1,4 +1,4 @@
/*-- The Summit --*/
/*-- The Cavern --*/
protected func Initialize()
{
@ -11,10 +11,10 @@ protected func Initialize()
d += 10;
pGoal->SetStartpoint(x, y);
// Set some checkpoints.
for (var i = 0; d < LandscapeHeight()-400; i++)
for (var i = 0; d < LandscapeHeight()-350; i++)
{
var mode = RACE_CP_Check;
d += RandomX(150,300);
d += RandomX(150,250);
if (!FindPosInMat(x, y, "Tunnel", 0, LandscapeHeight()-d-80, LandscapeWidth(), 80, 20) || !Random(3))
FindPosInMat(x, y, "Sky", 0, LandscapeHeight()-d-80, LandscapeWidth(), 80, 20);
else