Merge branch 'movement'

Günther Brammer 2012-07-13 23:27:14 +02:00
commit f41590d71f
107 changed files with 1876 additions and 439 deletions

View File

@ -144,7 +144,7 @@ if(MSVC_VERSION)
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
list(APPEND OC_CXX_FLAGS "-Wall -Wextra -Wredundant-decls -Wendif-labels -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Winit-self -Wsign-promo -Wno-reorder -Wno-unused-parameter -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo")
list(APPEND OC_CXX_FLAGS "-Wall -Wextra -Wredundant-decls -Wendif-labels -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Winit-self -Wsign-promo -Wno-reorder -Wno-unused-parameter -Wnon-virtual-dtor -Woverloaded-virtual")
endif()
if(WIN32 AND MINGW)

View File

@ -27,9 +27,9 @@ noinst_LIBRARIES = lib.a
if RECENT_GCC
WARNING_FLAGS = -Wall -Wextra -Wredundant-decls -Wendif-labels -Wpointer-arith \
-Wcast-qual -Wcast-align -Wwrite-strings -Winit-self -Wsign-promo \
-Wno-reorder -Wno-unused-parameter -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo
-Wno-reorder -Wno-unused-parameter -Wnon-virtual-dtor -Woverloaded-virtual
##-Wmissing-format-attribute -Wdisabled-optimization -Wlogical-op
##-Weffc++ -Wold-style-cast -Woverloaded-virtual -Wunsafe-loop-optimizations
##-Weffc++ -Wold-style-cast -Wunsafe-loop-optimizations
else
WARNING_FLAGS = -Wall
endif

View File

@ -42,14 +42,14 @@ void f(struct D&&); int main() { return 0; }
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_RANLIB
# Automake 1.12 breaks if this isn't run unconditionally
AC_PROG_OBJCXX
case $host in
*-*-mingw32* | *-*-cygwin* | *-*-windows*)
win32=true; osx=false;;
*-*-darwin*)
win32=false; osx=true;
m4_ifdef([AC_PROG_OBJCXX], [AC_PROG_OBJCXX], [AC_MSG_ERROR([this configure script was created with an autoconf version older than 2.65 and does not support macosx.])])
;;
win32=false; osx=true;;
*)
win32=false; osx=false;;
esac

View File

@ -74,6 +74,7 @@ color:#222222;
}
h1 {
font-family: Endeavour, Verdana, Sans-serif;
font-size: 2em;
font-weight: normal;
margin-top: 1.32em;

View File

@ -173,6 +173,20 @@
<col>postfix</col>
<col>bool, any/any</col>
</row>
<row>
<col>9l</col>
<col>===</col>
<col>Returns whether a and b refer to the same thing.</col>
<col>postfix</col>
<col>bool, any/any</col>
</row>
<row>
<col>9l</col>
<col>!==</col>
<col>Returns whether a and b do not refer to the same thing.</col>
<col>postfix</col>
<col>bool, any/any</col>
</row>
<row>
<col>8l</col>
<col>&amp;</col>
@ -310,6 +324,10 @@ while(<strong>++somevar</strong> &lt; 10)
<part>
<text>The <code>??</code> operator is called the nil-coalescing operator. It can be used to specify a default value for an expression or function call that may evaluate to <code>nil</code>.</text>
</part>
<h id="equality">The equality operators <code>==</code>, <code>!=</code>, <code>===</code> and <code>!==</code></h>
<part>
<text>The shorter operators basically consider more things equal. For example, two arrays with the same contents are equal, but === only returns true when both sides of the operator contain the same array. This matters mostly when arrays or proplists are modified. Modification can change the return value of the <code>==</code>/<code>!=</code> operators, but not of the <code>===</code>/<code>!==</code> operators.</text>
</part>
<h id="prio">Priority and Associating</h>
<part>
<text>This subject shows how operator priority is evaluated in detail.</text>

View File

@ -34,10 +34,10 @@ protected func Initialize()
CreateObject(Chest, 610, 340, NO_OWNER);
CreateObject(Chest, 355, 390, NO_OWNER);
AddEffect("IntFillChests", nil, 100, 2 * 36, this);
AddEffect("IntFillChests", nil, 100, 2 * 36, nil);
// Smooth brick edges.
AddEffect("ChanneledWind", nil, 100, 1, this);
AddEffect("Balloons", nil, 100, 100, this);
AddEffect("ChanneledWind", nil, 100, 1, nil);
AddEffect("Balloons", nil, 100, 100, nil);
// Moving bricks.
var brick;

View File

@ -10,9 +10,11 @@ func Initialize()
score = [];
boss = false;
wave = 1;
// Set scoreboard caption.
SetScoreboardData(SBRD_Caption, SBRD_Caption, "$ScoreCaption$", SBRD_Caption);
SetScoreboardData(SBRD_Caption, SBRD_Rockets, "{{Goal_SaveTheWindmills}}", SBRD_Caption);
// init scoreboard
Scoreboard->Init(
[{key = "windmills", title = Goal_SaveTheWindmills, sorted = true, desc = true, default = 0, priority = 80}]
);
Scoreboard->SetTitle("$ScoreCaption$");
// Remove settlement eval data.
HideSettlementScoreInEvaluation(true);
inherited(...);
@ -48,8 +50,7 @@ public func IncShotScore(int plr)
score[plrid]++;
if (plr != NO_OWNER)
{
SetScoreboardData(plrid, SBRD_Rockets, Format("%d", score[plrid]), score[plrid]);
SortScoreboard(SBRD_Rockets, true);
Scoreboard->SetPlayerData(plr, "windmills", score[plrid]);
}
NotifyHUD();
}
@ -80,9 +81,8 @@ protected func InitializePlayer(int plr)
{
var plrid = GetPlayerID(plr);
score[plrid] = 0;
// Create scoreboard player entry for this player.
SetScoreboardData(plrid, SBRD_Caption, GetTaggedPlayerName(plr), SBRD_Caption);
SetScoreboardData(plrid, SBRD_Rockets, Format("%d", score[plrid]), score[plrid]);
// Create scoreboard player entry for this player
Scoreboard->NewPlayerEntry(plr);
return _inherited(plr, ...);
}

View File

@ -802,6 +802,8 @@ func FxIntHangleStop(pTarget, effect, iReasonm, fTmp)
{
PopActionSpeed("Hangle");
if(fTmp) return;
// Delayed stop request
if (effect.request_stop) SetComDir(COMD_Stop);
}
func FxIntHangleTimer(pTarget, effect, iTime)

View File

@ -1,5 +1,5 @@
[DefCore]
id=Environment
id=Ambience
Version=4,10,0,0
Category=C4D_StaticBack
Width=1

View File

Before

Width:  |  Height:  |  Size: 91 B

After

Width:  |  Height:  |  Size: 91 B

View File

@ -0,0 +1,5 @@
This folder contains objects that have purely decorative purpose, so that they can be added and removed from any scenario without having any impact on the gameplay.
That means that if you decide to give objects in this folder a meaning beyond decoration, you should move them out into a proper place and also remove them from the proplist "Environment_Attributes" found in Ambience.ocd/Script.c - by the conventions you are guaranteed that nothing will break when you do that.
For example you could move Ambience_Zicadas into Animals.ocd, give them the ID "Zicadas" and remove the "Zicadas" entry from the proplist - or just set the "ID" field of the "Zicadas" entry to "nil".
You are encouraged to use objects from this folder through the function "CreateEnvironmentObjects" which guarantees full backwards and forwards compatibility. However, all objects in this folder also have Place()-methods if you need to place them manually.

View File

@ -1,5 +1,5 @@
/**
VisualEnvironment
Ambience
Cares about the placement of purely visual objects.
The placement uses categories and thus is forward-compatible.
*/
@ -28,7 +28,7 @@ static const Environment_Attributes =
},
Zicadas = {
ID = Environment_Zicadas,
ID = Ambience_Zicadas,
},
Frogs = {

View File

@ -1,5 +1,5 @@
[DefCore]
id=Environment_Zicadas
id=Ambience_Zicadas
Version=4,10,0,0
Category=C4D_StaticBack
Width=1

View File

@ -3,7 +3,6 @@
Author: Maikel
Capture the flag of the opposing team and bring it to your base to gain points.
TODO: Scoreboard.
--*/
@ -11,10 +10,24 @@
local score_list;
func ScoreboardTeamID(int team)
{
return team + 1000;
}
protected func Initialize()
{
score_list = [];
// init scoreboard
Scoreboard->Init(
[
{key = "title", title = "Teams"},
{key = "ctf", title = Goal_CaptureTheFlag, sorted = true, desc = true, default = 0, priority = 80}
]
);
Scoreboard->SetTitle("Capture the Flag");
return _inherited(...);
}
@ -39,7 +52,9 @@ public func SetFlagBase(int team, int x, int y)
public func AddTeamScore(int team)
{
score_list[team]++;
UpdateScoreboard(team);
Scoreboard->SetData(ScoreboardTeamID(team), "ctf", score_list[team]);
if (score_list[team] >= GetScoreGoal())
EliminateOthers(team);
return;
@ -57,11 +72,14 @@ private func EliminateOthers(int win_team)
return;
}
protected func InitializePlayer(int plr)
protected func InitializePlayer(int plr, int x, int y, object base, int team)
{
// Join new clonk.
JoinPlayer(plr);
InitScoreboard(GetPlayerTeam(plr));
// make scoreboard entry for team
Scoreboard->NewEntry(ScoreboardTeamID(team), GetTaggedTeamName(team));
// Broadcast to scenario.
GameCall("OnPlayerRelaunch", plr);
return _inherited(plr, ...);
@ -172,33 +190,4 @@ private func GetPlayerInTeamCount(int team)
return cnt;
}
/*-- Scoreboard --*/
static const SBRD_Score = 1;
private func InitScoreboard(int team)
{
// Scoreboard caption
if (GetScoreGoal() == 1)
SetScoreboardData(SBRD_Caption, SBRD_Caption, "$MsgScoreboard1$", SBRD_Caption);
else
SetScoreboardData(SBRD_Caption, SBRD_Caption, Format("$MsgScoreboardX$", GetScoreGoal()), SBRD_Caption);
// Team name
SetScoreboardData(team, SBRD_Caption, GetTaggedTeamName(team), team);
// Team score
SetScoreboardData(SBRD_Caption, SBRD_Score, "{{Goal_CaptureTheFlag}}", SBRD_Caption);
SetScoreboardData(team, SBRD_Score, Format("%d", 0), 0);
return;
}
private func UpdateScoreboard(int team)
{
// Update the team's score.
var score = score_list[team];
SetScoreboardData(team, SBRD_Score, Format("%d", score), score);
// Sort descending w.r.t. score.
SortScoreboard(SBRD_Score, true);
return;
}
local Name = "$Name$";

View File

@ -9,7 +9,6 @@
#include Scoreboard_KillStreak
#include Scoreboard_Death
#include Scoreboard_Kill
#include Scoreboard_Player
local maxkills;
@ -45,10 +44,7 @@ protected func RelaunchPlayer(int plr, int killer)
JoinPlayer(plr);
// Scenario script callback.
GameCall("OnPlayerRelaunch", plr);
// Show scoreboard for a while & sort.
SortScoreboard(Scoreboard_KillStreak->GetKillStreakCol(), true);
SortScoreboard(Scoreboard_Death->GetDeathCol(), true);
SortScoreboard(Scoreboard_Kill->GetKillCol(), true);
// Show scoreboard for a while
DoScoreboardShow(1, plr + 1);
Schedule(this,Format("DoScoreboardShow(-1, %d)", plr + 1), 35 * MIME_ShowBoardTime);
NotifyHUD();

View File

@ -20,6 +20,7 @@ SearchPosition();
*/
#include Library_Goal
#include Scoreboard_Death
local player_points;
local player_deaths;
@ -37,6 +38,10 @@ func Initialize()
SetRadius(300);
SetPointLimit(10);
Scoreboard->Init(
[{key = "koth", title = Goal_KingOfTheHill, sorted = true, desc = true, default = 0, priority = 80}]
);
Scoreboard->SetTitle("King of the Hill");
//CalculatePosition();
ScheduleCall(this, "PostInitialize", 3);
return _inherited(...);
@ -44,7 +49,6 @@ func Initialize()
func PostInitialize()
{
ScheduleCall(this, "RefreshScoreboard", 1);
Init();
}
@ -113,11 +117,12 @@ func DoPoint(int player, int count)
if (count == nil)
count = 1;
player_points[player] = Max(player_points[player] + count, 0);
Scoreboard->SetPlayerData(player, "koth", player_points[player]);
}
protected func InitializePlayer(int plr, int x, int y, object base, int team)
{
ScheduleCall(this, "RefreshScoreboard", 1);
Scoreboard->NewPlayerEntry(plr);
player_suicides[plr]=0;
Goal_Melee->MakeHostileToAll(plr, team);
@ -131,7 +136,6 @@ public func IsFulfilled()
func OnClonkDeath(object clonk, int killer)
{
ScheduleCall(this, "RefreshScoreboard", 1);
if (clonk->GetAlive()) return;
if (GetPlayerName(clonk->GetOwner()))
@ -267,27 +271,6 @@ private func GetTeamPoints()
return ret;
}
static const SBRD_Deaths=2;
static const SBRD_Points=1;
func RefreshScoreboard()
{
SetScoreboardData(SBRD_Caption,SBRD_Caption,"King of the Hill",SBRD_Caption);
SetScoreboardData(SBRD_Caption,SBRD_Points,Format("{{Sword}} / %d", GetPointLimit()),SBRD_Caption);
SetScoreboardData(SBRD_Caption,SBRD_Deaths,"{{Clonk}}",SBRD_Caption);
for(var cnt=0;cnt<GetPlayerCount();cnt++)
{
var plr=GetPlayerByIndex(cnt);
SetScoreboardData(plr+2,SBRD_Caption,GetTaggedPlayerName(plr),SBRD_Caption);
SetScoreboardData(plr+2,SBRD_Points,Format("%d", player_points[plr]),player_points[plr]);
SetScoreboardData(plr+2,SBRD_Deaths,Format("%d", player_deaths[plr]),player_deaths[plr]);
}
SortScoreboard(SBRD_Deaths,1);
SortScoreboard(SBRD_Points,1);
}
public func GetShortDescription(int plr)
{

View File

@ -17,7 +17,6 @@
#include Scoreboard_Kill
//#include Scoreboard_Death
#include Scoreboard_Relaunch
#include Scoreboard_Player
// Some static constants.
static const MIME_RelaunchCount = 5; // Number of relaunches.
@ -87,10 +86,7 @@ protected func RelaunchPlayer(int plr, int killer)
JoinPlayer(plr);
// Scenario script callback.
GameCall("OnPlayerRelaunch", plr);
// Show scoreboard for a while & sort.
SortScoreboard(Scoreboard_KillStreak->GetKillStreakCol(), true);
SortScoreboard(Scoreboard_Kill->GetKillCol(), true);
SortScoreboard(Scoreboard_Relaunch->GetRelaunchCol(), true);
// Show scoreboard for a while.
DoScoreboardShow(1, plr + 1);
Schedule(this,Format("DoScoreboardShow(-1, %d)", plr + 1), 35 * MIME_ShowBoardTime);
return; // _inherited(plr, killer, ...);

View File

@ -324,7 +324,7 @@ protected func InitializePlayer(int plr, int x, int y, object base, int team)
if (!team_list[team])
team_list[team] = 0;
// Scoreboard.
InitScoreboard();
Scoreboard->NewPlayerEntry(plr);
UpdateScoreboard(plr);
DoScoreboardShow(1, plr + 1);
JoinPlayer(plr);
@ -384,10 +384,14 @@ private func InitScoreboard()
var caption = Format("$MsgCaptionX$", cp_count);
else
var caption = "$MsgCaptionNone$";
// The above row.
SetScoreboardData(SBRD_Caption, SBRD_Caption, caption, SBRD_Caption);
SetScoreboardData(SBRD_Caption, SBRD_Checkpoints, Format("{{%i}}", ParkourCheckpoint), SBRD_Caption);
SetScoreboardData(SBRD_Caption, SBRD_BestTime, "T", SBRD_Caption);
Scoreboard->Init(
[
{key = "checkpoints", title = ParkourCheckpoint, sorted = true, desc = true, default = 0, priority = 80},
{key = "besttime", title = "T", sorted = true, desc = true, default = 0, priority = 70}
]
);
Scoreboard->SetTitle(caption);
return;
}
@ -396,14 +400,9 @@ private func UpdateScoreboard(int plr)
if (finished)
return;
var plrid = GetPlayerID(plr);
// The player name.
SetScoreboardData(plrid, SBRD_Caption, GetTaggedPlayerName(plr), SBRD_Caption);
// The player scores.
SetScoreboardData(plrid, SBRD_Checkpoints, Format("%d", plr_list[plrid]), plr_list[plrid]);
SetScoreboardData(plrid, SBRD_BestTime, TimeToString(GetPlrExtraData(plr, time_store)), GetPlrExtraData(plr, time_store));
// Sort.
SortScoreboard(SBRD_BestTime, false);
SortScoreboard(SBRD_Checkpoints, true);
Scoreboard->SetPlayerData(plr, "checkpoints", plr_list[plrid]);
var bt = GetPlrExtraData(plr, time_store);
Scoreboard->SetPlayerData(plr, "besttime", TimeToString(bt), bt);
return;
}

View File

@ -22,11 +22,14 @@ local markers; // Array, the gui-markers.
local carryheavy; // Object, optional inventory-button only shown when clonk is carrying a carry-heavy object
local wealth; // Object, displays wealth of the player
local progress_bar_links;
protected func Construction()
{
actionbar = [];
markers = [];
inventory = [];
progress_bar_links = [];
// find all clonks of this crew which do not have a selector yet (and can have one)
for(var i=GetCrewCount(GetOwner())-1; i >= 0; --i)
@ -184,12 +187,34 @@ func UpdateInventory()
var c = GetCursor(GetOwner());
if(!c) return 1;
// sort out old progress bars
if(GetLength(progress_bar_links))
{
var old_progress_bar_links = progress_bar_links[:];
progress_bar_links = [];
for(var bar in old_progress_bar_links)
{
if(!bar.effect) continue;
PushBack(progress_bar_links, bar);
}
}
// update inventory-slots
for(var i=0; i<GetLength(inventory); i++)
{
var item = c->GetItem(inventory[i]->GetSlotId());
inventory[i]->SetSymbol(item);
inventory[i]->SetUnselected();
inventory[i]->ClearProgressBarLink();
// re-add progress bar if possible
for(var bar in progress_bar_links)
{
if(bar.obj != item) continue;
inventory[i]->SetProgressBarLink(bar.effect);
break;
}
}
// update hand-indicator
@ -206,6 +231,14 @@ func UpdateInventory()
}
}
// sets the link of the progress bar for a certain slot
// the link is an effect that has the properties "max" and "current"
func SetProgressBarLinkForObject(object what, proplist e)
{
PushBack(progress_bar_links, {obj = what, effect = e});
ScheduleUpdateInventory();
}
// Shows the Carryheavy-Inventoryslot if obj is set
// Removes it if it's nil
func OnCarryHeavyChange(object obj)

View File

@ -7,4 +7,7 @@ Height=64
Offset=-32,-32
StretchGrowth=1
Rotate=1
Oversize=1
Oversize=1
Vertices=1
VertexX=0
VertexY=0

View File

@ -7,6 +7,8 @@ local selected;
local position;
local controller;
local progress_bar, progress_bar_last_max;
public func SetHUDController(object c) { controller = c; }
protected func Construction()
@ -187,3 +189,60 @@ public func OnMouseOut(int plr)
SetGraphics(nil, nil);
}
// progress bar handling
// "link" always refers to an effect with the properties "max" and "current"
func ClearProgressBarLink()
{
if(GetEffect("UpdateProgressBar", this))
RemoveEffect("UpdateProgressBar", this);
if(progress_bar)
{
progress_bar->Close();
progress_bar = nil;
}
}
func SetProgressBarLink(proplist effect)
{
if(GetEffect("UpdateProgressBar", this)) return; // not another one
AddEffect("UpdateProgressBar", this, 1, Min(effect.Interval, 25), this, nil, effect);
}
func FxUpdateProgressBarStart(target, effect, temp, delegate)
{
if(temp) return;
effect.other = delegate;
}
func FxUpdateProgressBarTimer(target, effect, time)
{
if(!effect.other) return -1;
SetProgressBarValue(effect.other.current, effect.other.max);
}
public func SetProgressBarValue(int value, int max)
{
if(value == nil)
{
if(progress_bar) progress_bar->Close();
return true;
}
if(progress_bar_last_max != max)
if(progress_bar)
{
progress_bar->Close();
progress_bar = nil;
}
progress_bar_last_max = max;
if(!progress_bar)
{
progress_bar = this->CreateProgressBar(GUI_PieProgressBar, max, value, 30, GetOwner(), {x=0, y=0}, VIS_Owner, {size=1600, color = RGB(100, 255, 25), back_color = RGBa(100, 50, 0, 100)});
progress_bar->MakeHUDElement();
progress_bar->SetPlane(this.Plane-1);
}
progress_bar->SetValue(value);
return true;
}

View File

@ -26,6 +26,9 @@ public func SetMenuSpacing(int distance) { menu_spacing = distance; }
/** Sets the distance from the outer edges to the outer objects */
public func SetMenuBorder(int distance) { menu_border = distance; }
/** Sets the background color of the menu */
public func SetBackgroundColor(int rgb) { SetClrModulation(rgb, 1); }
public func Construction()
{
rowitemcount = nil;
@ -52,7 +55,8 @@ public func UpdateMenu()
if(ric == nil)
{
// we use the square root to get a square layout! trololo!
ric = Sqrt(itemcount);
// must not be 0
ric = Max(1, Sqrt(itemcount));
rc = ric;
if(itemcount > rc*rc)
ric += 1;

View File

@ -0,0 +1,12 @@
[DefCore]
id=GUI_BarProgressBar
Version=4,10,0,0
Category=C4D_Vehicle
Width=8
Height=8
Offset=-4,-4
Vertices=1
VertexX=0
VertexY=0
VertexFriction=20

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

View File

@ -0,0 +1,152 @@
/**
BarProgressBar
Shows progress.
additional data the bar takes through the "data" parameter:
bars: number of bars
color: color of filled bars
back_color: color of empty bars
size: size of the bar 1000 = 100%
*/
local Name = "$Name$";
local Description = "$Description$";
local maximum, current, timeout_time;
local bars;
local color, back_color, number_of_bars, size;
local ActMap=
{
Attach =
{
Prototype = Action,
Name="Attach",
Procedure=DFA_ATTACH,
NextAction="Be",
Length=1,
FacetBase=1,
AbortCall = "AttachTargetLost"
}
};
func Init(to, max, cur, timeout, offset, visibility, data)
{
maximum = max;
current = cur;
timeout_time = timeout;
bars = [];
number_of_bars = data.bars ?? 10;
color = data.color ?? RGB(1, 255, 1);
back_color = data.back_color ?? RGBa(1, 1, 1, 150);
size = data.size ?? 1000;
if(timeout_time)
{
var e = AddEffect("TimeOut", this, 1, BoundBy(timeout_time/2, 5, 35), this);
e.t = timeout_time;
}
bars[0] = this;
for(var i = 1; i < number_of_bars; ++i)
bars[i] = CreateObject(GetID(), 0, 0, GetOwner());
var cnt = 0;
for(var obj in bars)
{
obj->Set(to, cnt, number_of_bars, size, offset, visibility);
++cnt;
}
AddEffect("LifeCheck", to, 1, 0, this);
Update();
}
func FxLifeCheckStop(target, effect, cause, temp)
{
if(temp) return;
if(this)
this->RemoveObject();
}
func FxTimeOutTimer(target, effect, time)
{
effect.t -= effect.Interval;
if(effect.t > 0) return 1;
Close();
return -1;
}
func Update()
{
var l = GetLength(bars);
var p = (current * 100) / maximum;
var last_colored = (l * p) / 100;
for(var i = 0; i < l; ++i)
{
var obj = bars[i];
if(i >= last_colored)
{
obj->SetClrModulation(back_color);
continue;
}
obj->SetClrModulation(color);
}
}
func Close()
{
RemoveObject();
}
func Destruction()
{
if(GetType(bars) == C4V_Array)
for(var i = GetLength(bars) - 1; i > 0; --i) // off-by-one on purpose
{
var obj = bars[i];
if(obj)
obj->RemoveObject();
}
}
func SetValue(int to)
{
current = BoundBy(to, 0, maximum);;
var e = GetEffect("TimeOut", this);
if(e)
e.t = timeout_time;
Update();
}
func DoValue(int change)
{
SetValue(current + change);
}
func Initialize()
{
}
func AttachTargetLost()
{
return RemoveObject();
}
func Set(to, number, max_num, size, offset, visibility)
{
SetAction("Attach", to);
var x = 0 - offset.x;
var y = (6 * number * size) / 1000 - offset.y;
SetPosition(GetX() - x, GetY() - y + 8); // for good position in first frame
SetVertexXY(0, x + to->GetVertex(0, VTX_X), y + to->GetVertex(0, VTX_Y));
SetObjDrawTransform(size, 0, 0, 0, size, (6 * (1000 - size)));
this.Visibility = visibility;
}

View File

@ -0,0 +1,2 @@
Name=Ladebalken
Description=Zeigt Fortschritt.

View File

@ -0,0 +1,2 @@
Name=Progress Ring
Description=Shows progress.

View File

@ -0,0 +1,12 @@
[DefCore]
id=GUI_CustomImageProgressBar
Version=4,10,0,0
Category=C4D_Vehicle
Width=64
Height=64
Offset=-32,-32
Vertices=1
VertexX=0
VertexY=0
VertexFriction=20

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,178 @@
/**
CustomImageProgressBar
Shows progress.
Takes an image-definition that is used as the source definition for SetGraphics.
The definition can have the callback "GetBarGraphicsName(int percent)" to return a string for a graphics file that is used for SetGraphics.
It can also have GetBarColor(int percent) to return a proplist with {r = ?, g = ?, b = ?} to get the color shown.
additional data the bar takes through the "data" parameter:
image: definition to use as graphics
size: size of the progress bar 1000 = 100%
*/
local Name = "$Name$";
local Description = "$Description$";
local current, maximum, timeout_time;
local image, size;
local lr, lg, lb, la, graphics_name;
local ActMap=
{
Attach =
{
Prototype = Action,
Name="Attach",
Procedure=DFA_ATTACH,
NextAction="Be",
Length=1,
FacetBase=1,
AbortCall = "AttachTargetLost"
}
};
func Init(to, max, cur, timeout, offset, visibility, data)
{
maximum = max;
current = cur;
timeout_time = timeout;
la = 255;
size = data.size ?? 1000;
image = data.image ?? Rock;
if(timeout_time)
{
var e = AddEffect("TimeOut", this, 1, BoundBy(timeout_time/2, 5, 35), this);
e.t = timeout_time;
}
AddEffect("LifeCheck", to, 1, 0, this);
SetAction("Attach", to);
var x = -offset.x;
var y = -offset.y;
SetPosition(GetX() - x, GetY() - y + 32); // for good position in first frame
SetVertexXY(0, x + to->GetVertex(0, VTX_X), y + to->GetVertex(0, VTX_Y));
this.Visibility = visibility;
Update();
}
func FxLifeCheckStop(target, effect, cause, temp)
{
if(temp) return;
if(this)
this->RemoveObject();
}
func FxTimeOutTimer(target, effect, time)
{
effect.t -= effect.Interval;
if(effect.t > 0) return 1;
if(!GetEffect("FadeOut", this))
FadeOut();
return 1;
}
func FadeOut()
{
AddEffect("FadeOut", this, 1, 3, this);
}
func FxFadeOutTimer(target, effect, time)
{
if(la <= 20) return Close();
la -= 15;
SetClrModulation(RGBa(lr, lg, lb, la));
}
func Update()
{
var p = (current * 100) / maximum;
var charge = (255 * p) / 100;
var clr;
if(clr = image->~GetBarColor(p))
{
lr = clr.r;
lg = clr.g;
lb = clr.b;
}
else
{
lr = charge;
lg = 255 - charge;
lb = 255;
}
SetGraphics(image->~GetBarGraphicsName(p), image, 0, GFXOV_MODE_IngamePicture, nil, GFX_BLIT_Custom);
SetClrModulation(RGB(lr, lg, lb));
SetObjDrawTransform(size, 0, 0, 0, size);
}
func Close()
{
RemoveObject();
}
func Destruction()
{
}
func SetValue(int to)
{
current = BoundBy(to, 0, maximum);;
var e = GetEffect("TimeOut", this);
if(e)
e.t = timeout_time;
if(GetEffect("FadeOut", this))
RemoveEffect("FadeOut", this);
Update();
}
func DoValue(int change)
{
SetValue(current + change);
}
func Initialize()
{
}
func SetParallax(f)
{
if(f)
{
SetCategory(GetCategory() | C4D_Parallax);
this.Parallaxity = [0, 0];
}
else
{
SetCategory(GetCategory() & ~C4D_Parallax);
this.Parallaxity = nil;
}
return true;
}
func SetPlane(int to)
{
if(to == nil) return;
this.Plane = to;
return true;
}
func MakeHUDElement()
{
SetCategory(C4D_StaticBack | C4D_IgnoreFoW | C4D_Foreground | C4D_Parallax);
SetParallax();
}
func AttachTargetLost()
{
return RemoveObject();
}

View File

@ -0,0 +1,2 @@
Name=Ladebalken
Description=Zeigt Fortschritt.

View File

@ -0,0 +1,2 @@
Name=Progress Ring
Description=Shows progress.

View File

@ -0,0 +1,12 @@
[DefCore]
id=GUI_CustomRingProgressBar
Version=4,10,0,0
Category=C4D_Vehicle
Width=8
Height=8
Offset=-4,-4
Vertices=1
VertexX=0
VertexY=0
VertexFriction=20

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,73 @@
/**
CustomRingProgressBar
Shows progress.
additional data the bar takes through the "data" parameter:
radius: radius of the bar in pixels, the amount of points is dynamically adjusted
image: definition to show when filled
back_image: definition to show when not filled, defaults to image
color: foreground color
back_color: background color
*/
#include GUI_RingProgressBar
local Name = "$Name$";
local Description = "$Description$";
local image, back_image;
local color, back_color;
local ActMap=
{
Attach =
{
Prototype = Action,
Name="Attach",
Procedure=DFA_ATTACH,
NextAction="Be",
Length=1,
FacetBase=1,
AbortCall = "AttachTargetLost"
}
};
func Init(to, max, cur, timeout, offset, visibility, data)
{
data.image = data.image ?? GUI_RingProgressBar;
data.back_image = data.back_image ?? data.image;
data.color = data.color ?? RGBa(255, 255, 255,200);
data.back_color = data.back_color ?? RGBa(50, 50, 50, 50);
image = data.image;
back_image = data.back_image;
color = data.color;
back_color = data.back_color;
return inherited(to, max, cur, timeout, offset, visibility, data);
}
func Update()
{
var l = GetLength(ring);
var p = (current * 100) / maximum;
var last_colored = (l * p) / 100;
for(var i = 0; i < l; ++i)
{
var obj = ring[i];
if(i >= last_colored)
{
obj->SetGraphics(nil, back_image, 0, GFXOV_MODE_ObjectPicture, nil, GFX_BLIT_Custom);
obj->SetClrModulation(back_color);
}
else
{
obj->SetGraphics(nil, image, 0, GFXOV_MODE_ObjectPicture, nil, GFX_BLIT_Custom);
obj->SetClrModulation(color);
}
obj->Rotate(obj.my_angle + 180, 0, 0);
}
}

View File

@ -0,0 +1,2 @@
Name=Ladebalken
Description=Zeigt Fortschritt.

View File

@ -0,0 +1,2 @@
Name=Progress Ring
Description=Shows progress.

View File

@ -0,0 +1,5 @@
[DefCore]
id=GUI_ProgressBar
Version=4,10,0,0
Category=C4D_StaticBack

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 B

View File

@ -0,0 +1,12 @@
[DefCore]
id=GUI_PieProgressBar
Version=4,10,0,0
Category=C4D_Vehicle
Width=8
Height=8
Offset=-4,-4
Vertices=1
VertexX=0
VertexY=0
VertexFriction=20

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

View File

@ -0,0 +1,116 @@
/**
PieProgressBar
Shows progress.
additional data the bar takes through the "data" parameter:
size: size of the pie, 1000 = 100%
color: foreground color
back_color: background color
*/
#include GUI_RingProgressBar
local Name = "$Name$";
local Description = "$Description$";
local size;
local color, back_color;
local ActMap=
{
Attach =
{
Prototype = Action,
Name="Attach",
Procedure=DFA_ATTACH,
NextAction="Be",
Length=1,
FacetBase=1,
AbortCall = "AttachTargetLost"
}
};
func Init(to, max, cur, timeout, offset, visibility, data)
{
data.color = data.color ?? RGBa(255, 255, 255,200);
data.back_color = data.back_color ?? RGBa(50, 50, 50, 50);
size = data.size ?? 1000;
color = data.color;
back_color = data.back_color;
maximum = max;
current = cur;
timeout_time = timeout;
ring = [];
if(timeout_time)
{
var e = AddEffect("TimeOut", this, 1, BoundBy(timeout_time/2, 5, 35), this);
e.t = timeout_time;
}
var amount = 24;
ring[0] = this;
for(var i = 1; i < amount; ++i)
ring[i] = CreateObject(GetID(), 0, 0, GetOwner());
var cnt = 0;
for(var obj in ring)
{
obj->Set(to, 180 / amount + ((cnt * 360) / amount), offset, visibility, size);
++cnt;
}
AddEffect("LifeCheck", to, 1, 0, this);
Update();
}
func Update()
{
var l = GetLength(ring);
var p = (current * 100) / maximum;
var last_colored = (l * p) / 100;
for(var i = 0; i < l; ++i)
{
var obj = ring[i];
if(i >= last_colored)
{
obj->SetClrModulation(back_color);
}
else
{
obj->SetClrModulation(color);
}
}
}
func Set(to, angle, offset, visibility, size)
{
SetAction("Attach", to);
var distance = (10 * size) / 1000;
var x = -Sin(angle, distance) - offset.x;
var y = +Cos(angle, distance) - offset.y;
SetPosition(GetX() - x, GetY() - y + 8); // for good position in first frame
SetVertexXY(0, x + to->GetVertex(0, VTX_X), y + to->GetVertex(0, VTX_Y));
my_angle = -angle;
Rotate(my_angle, 0, 0, (2500 * size) / 1000);
this.Visibility = visibility;
}
func Rotate (int r, int xoff, int yoff, size) {
var fsin=Sin(r, 1000), fcos=Cos(r, 1000);
size = size ?? 1000;
// set matrix values
SetObjDrawTransform (
(+fcos) * size / 1000, (+fsin) * size / 1000, ((1000-fcos)*xoff - fsin*yoff) * size / 1000,
(-fsin) * size / 1000, (+fcos) * size / 1000, ((1000-fcos)*yoff + fsin*xoff) * size / 1000
);
}

View File

@ -0,0 +1,2 @@
Name=Ladebalken
Description=Zeigt Fortschritt.

View File

@ -0,0 +1,2 @@
Name=Progress Ring
Description=Shows progress.

View File

@ -0,0 +1,12 @@
[DefCore]
id=GUI_RingProgressBar
Version=4,10,0,0
Category=C4D_Vehicle
Width=8
Height=8
Offset=-4,-4
Vertices=1
VertexX=0
VertexY=0
VertexFriction=20

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,205 @@
/**
RingProgressBar
Shows progress.
additional data the bar takes through the "data" parameter:
radius: radius of the bar in pixels, the amount of points is dynamically adjusted
amount: number of segments in the ring, usually calculates form radius
*/
local Name = "$Name$";
local Description = "$Description$";
local maximum, current, timeout_time;
local my_angle;
local ring;
local ActMap=
{
Attach =
{
Prototype = Action,
Name="Attach",
Procedure=DFA_ATTACH,
NextAction="Be",
Length=1,
FacetBase=1,
AbortCall = "AttachTargetLost"
}
};
func Init(to, max, cur, timeout, offset, visibility, data)
{
maximum = max;
current = cur;
timeout_time = timeout;
ring = [];
if(timeout_time)
{
var e = AddEffect("TimeOut", this, 1, BoundBy(timeout_time/2, 5, 35), this);
e.t = timeout_time;
}
var radius = data.radius ?? 20;
var amount = data.amount ?? BoundBy(radius, 8, 30);
ring[0] = this;
for(var i = 1; i < amount; ++i)
ring[i] = CreateObject(GetID(), 0, 0, GetOwner());
var cnt = 0;
for(var obj in ring)
{
obj->Set(to, radius, ((cnt * 360) / amount), offset, visibility);
++cnt;
}
AddEffect("LifeCheck", to, 1, 0, this);
Update();
}
func FxLifeCheckStop(target, effect, cause, temp)
{
if(temp) return;
if(this)
this->RemoveObject();
}
func FxTimeOutTimer(target, effect, time)
{
effect.t -= effect.Interval;
if(effect.t > 0) return 1;
Close();
return -1;
}
func Update()
{
var l = GetLength(ring);
var p = (current * 100) / maximum;
var last_colored = (l * p) / 100;
for(var i = 0; i < l; ++i)
{
var obj = ring[i];
if(i > last_colored)
{
obj->SetClrModulation(RGBa(10, 10, 10, 200));
continue;
}
var p = (i * 100) / l;
var charge = (255 * p) / 100;
var r = 255, g = 255;
if(p > 50) r = BoundBy(255 - charge * 2, 0, 255);
if(p < 50) g = BoundBy(charge * 2, 0, 255);
obj->SetClrModulation(RGBa(r, g, 1, 200));
}
}
func Close()
{
RemoveObject();
}
func Destruction()
{
if(GetType(ring) == C4V_Array)
for(var i = GetLength(ring) - 1; i > 0; --i) // off-by-one on purpose
{
var obj = ring[i];
if(obj)
obj->RemoveObject();
}
}
func SetValue(int to)
{
current = BoundBy(to, 0, maximum);;
var e = GetEffect("TimeOut", this);
if(e)
e.t = timeout_time;
Update();
}
func DoValue(int change)
{
SetValue(current + change);
}
func Initialize()
{
}
func SetParallax(f)
{
f = f ?? true;
for(var obj in ring)
{
if(f)
{
obj->SetCategory(obj->GetCategory() | C4D_Parallax);
obj.Parallaxity = [0, 0];
}
else
{
obj->SetCategory(obj->GetCategory() & ~C4D_Parallax);
obj.Parallaxity = nil;
}
}
return true;
}
func SetPlane(int to)
{
if(to == nil) return;
for(var obj in ring)
{
obj.Plane = to;
}
return true;
}
func MakeHUDElement()
{
for(var obj in ring)
{
obj->SetCategory(C4D_StaticBack | C4D_IgnoreFoW | C4D_Foreground | C4D_Parallax);
}
SetParallax();
}
func AttachTargetLost()
{
return RemoveObject();
}
func Rotate (int r, int xoff, int yoff) {
var fsin=Sin(r, 1000), fcos=Cos(r, 1000);
// set matrix values
SetObjDrawTransform (
+fcos, +fsin, (1000-fcos)*xoff - fsin*yoff,
-fsin, +fcos, (1000-fcos)*yoff + fsin*xoff
);
}
func Set(to, distance, angle, offset, visibility)
{
SetAction("Attach", to);
var x = -Sin(angle, distance) - offset.x;
var y = +Cos(angle, distance) - offset.y;
SetPosition(GetX() - x, GetY() - y + 8); // for good position in first frame
SetVertexXY(0, x + to->GetVertex(0, VTX_X), y + to->GetVertex(0, VTX_Y));
my_angle = -angle;
Rotate(my_angle, 0, 0);
this.Visibility = visibility;
}

View File

@ -0,0 +1,2 @@
Name=Ladebalken
Description=Zeigt Fortschritt.

View File

@ -0,0 +1,2 @@
Name=Progress Ring
Description=Shows progress.

View File

@ -0,0 +1,70 @@
/**
GUI_ProgressBar
Provides the interface used by different progress bars.
*/
local Name = "$Name$";
local Description = "$Description$";
// creates a progress bar of the given ID and returns it
global func CreateProgressBar(
ID /* ID of the progress bar */
, int max /* maximum value of the progress bar */
, int current /* starting value of the progress bar */
, int time_out /* time in frames after which the progress bar closes itself when not receiving updates, might be nil */
, int owner /* owner of the progress bar */
, proplist offset /* proplist {x = ?, y = ?} that specifies the offset of the progress bar relative to the calling object */
, int visibility /* visibility mask for the progress bar, f.e.: VIS_Owner | VIS_Allies */
, proplist data /* proplist with extra data that is passed to the progress bar */
)
{
if(!this) return;
owner = owner ?? NO_OWNER;
visibility = visibility ?? VIS_All;
offset = offset ?? {x = 0, y = 0};
max = max ?? 100;
current = current ?? 0;
data = data ?? {};
if(!ID)
FatalError("CreateProgressBar called without valid ID");
var obj = CreateObject(ID, 0, 0, owner);
obj->Init(this, max, current, time_out, offset, visibility, data);
return obj;
}
// closes the progress bar and usually removes it
func Close(){return _inherited(...);}
// sets the value of the progress bar, updates the progress bar
func SetValue(int to){return _inherited(to, ...);}
// changes the value of the progress bar by the specified amount, usually calls SetValue
func DoValue(int change){return _inherited(change, ...);}
// changes the offset {x = ?, y = ?} of the progress bar relative to the attached object (or global)
func SetOffset(proplist offset){return _inherited(offset, ...);}
// makes the progress bar 100% parallax
func SetParallax(){return _inherited(...);}
// sets the Plane property of the progress bar
func SetPlane(int to) {return _inherited(...);}
// makes the object a HUD element by setting parallaxity and the category C4D_StaticBack | C4D_IgnoreFoW | C4D_Foreground | C4D_Parallax
func MakeHUDElement() {return _inherited(...);}
// called once on creation by CreateProgressBar on the new bar
func Init(object to /* object to attach the bar to */
, int maximum /* maximum value of the progress bar (100%) */
, int current /* starting value of the progress bar (0 <= current <= maximum*/
, int timeout /* time in frames after which the progress bar should Close itself when not receiving updates, might be nil */
, proplist offset /* proplist with properties "x" and "y" that specifies the offset of the bar relative to the target object, the progress bar might provide standard values */
, proplist data /* proplist with additional data the progress bar can use */
)
{return _inherited(to, maximum, current, timeout, ...);}
// updates the visuals of the progress bar
func Update(){return _inherited(...);}

View File

@ -0,0 +1,12 @@
[DefCore]
id=GUI_SimpleProgressBar
Version=4,10,0,0
Category=C4D_Vehicle
Width=16
Height=16
Offset=-8,-8
Vertices=1
VertexX=0
VertexY=0
VertexFriction=20

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

View File

@ -0,0 +1,124 @@
/**
SimpleProgressBar
Shows progress.
additional data the bar takes through the "data" parameter:
color: color of the inside
back_color: color of the background
width: length of the bar in pixels
height: height of the bar in pixels
*/
local Name = "$Name$";
local Description = "$Description$";
local maximum, current, timeout_time;
local width, height, color, back_color;
local ActMap=
{
Attach =
{
Prototype = Action,
Name="Attach",
Procedure=DFA_ATTACH,
NextAction="Be",
Length=1,
FacetBase=1,
AbortCall = "AttachTargetLost"
}
};
func Init(to, max, cur, timeout, offset, visibility, proplist data)
{
maximum = max;
current = cur;
timeout_time = timeout;
width = data.width ?? 40;
height = data.height ?? 5;
if(timeout_time)
{
var e = AddEffect("TimeOut", this, 1, BoundBy(timeout_time/2, 5, 35), this);
e.t = timeout_time;
}
this.Visibility = visibility;
SetGraphics(nil, GetID(), 1, GFXOV_MODE_Base, nil, GFX_BLIT_Custom);
SetBarColor(data.color, data.back_color);
SetAction("Attach", to);
SetVertexXY(0, -offset.x, -offset.y);
AddEffect("LifeCheck", to, 1, 0, this);
Update();
}
func SetBarColor(c, b)
{
color = c ?? RGB(200, 200, 10);
back_color = b ?? RGB(1, 1, 1);
SetClrModulation(color, 1);
SetClrModulation(back_color, 0);
}
func FxLifeCheckStop(target, effect, cause, temp)
{
if(temp) return;
if(this)
this->RemoveObject();
}
func FxTimeOutTimer(target, effect, time)
{
effect.t -= effect.Interval;
if(effect.t > 0) return 1;
Close();
return -1;
}
func Update()
{
var p = (current * 100) / maximum;
var w = (width * 1000) / 16;
var l = (width * p * 10) / 16;
SetObjDrawTransform(w, 0, 0, 0, (height * 1000) / 16, 0, 0);
SetObjDrawTransform(l, 0, -(w-l) * 8, 0, (height * 800) / 16, 100, 1);
}
func Close()
{
RemoveObject();
}
func Destruction()
{
}
func SetValue(int to)
{
current = BoundBy(to, 0, maximum);;
var e = GetEffect("TimeOut", this);
if(e)
e.t = timeout_time;
Update();
}
func DoValue(int change)
{
SetValue(current + change);
}
func AttachTargetLost()
{
return RemoveObject();
}

View File

@ -0,0 +1,2 @@
Name=Ladebalken
Description=Zeigt Fortschritt.

View File

@ -0,0 +1,2 @@
Name=Progress Ring
Description=Shows progress.

View File

@ -0,0 +1,2 @@
Name=GUI_ProgressBar
Description=Stellt ein Interface für Fortschrittsleisten zur Verfügung.

View File

@ -0,0 +1,2 @@
Name=GUI_ProgressBar
Description=Provides the interface used by different progress bars.

View File

@ -0,0 +1,7 @@
[DefCore]
id=Scoreboard
Version=4,10,0,0
Category=C4D_StaticBack
Width=1
Height=1
Offset=-1,-1

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

View File

@ -0,0 +1,277 @@
/**
Scoreboard
Provides an additional abstraction layer on top of the scoreboard-functions
Attention: Do not include this. Use the function as specified with f.e. Scoreboard->Init(...)
*/
// do not manipulate externally
static Scoreboard_keys; // [{key = ?, title = ?, ..}, ..]
static Scoreboard_data; // [{key = value, ..}, ..]
static Scoreboard_unique_ids;
static Scoreboard_title_set;
static const Scoreboard_Y_title = SBRD_Caption;
static const Scoreboard_X_title = SBRD_Caption;
// wrapper for Scoreboard->NewEntry, adds a new entry for a player with the tagged player name as the title
public func NewPlayerEntry(int plr)
{
return Scoreboard->NewEntry(GetPlayerID(plr), GetTaggedPlayerName(plr));
}
// adds a new entry to the scoreboard, will return the ID of the added entry
// the parameter new_id might be nil in which case a unique new ID is chosen
public func NewEntry(
int new_id /* unique ID for the new entry, can be nil */
, string new_title /* text for the first column */
)
{
// check for duplicates
if(new_id)
{
var index = -1;
for(var i = 0; i < GetLength(Scoreboard_data); ++i)
{
if(Scoreboard_data[i].ID != new_id) continue;
index = i;
break;
}
// duplicate?
if(index != -1) return nil;
}
else // no ID provided, get new one
{
new_id = ++Scoreboard_unique_ids;
}
PushBack(Scoreboard_data, {ID = new_id, title = new_title});
Scoreboard->Update(new_id);
return new_id;
}
// sets a value for a specific key of a scoreboard entry for a player and updates it
// that entry must have been created earlier with ScoreboarNewPlayerEntry or manually with Scoreboard->NewEntry
public func SetPlayerData(
int plr /* player number for the player entry to manipulate */
, string key /* name of the key assign value to */
, to /* value to assign, might be ID, string, int or bool */
, int sort_parameter /* parameter used for sorting. if nil, 'to' is used if possible*/
)
{
var ID = GetPlayerID(plr);
return Scoreboard->SetData(ID, key, to, sort_parameter);
}
// sets a value for a specific key of any entry in the scoreboard and updates it
// the entry must have been created with Scoreboard->NewEntry earlier
public func SetData(
int ID /* ID of the entry to manipulate */
, string key /* name of the key to assign value to */
, to /* new value of the key, might be int, string bool or id */
, int sort_parameter /* parameter that is used for sorting of the entry. if nil, 'to' is used if possible*/
)
{
var index = -1;
for(var i = 0; i < GetLength(Scoreboard_data); ++i)
{
if(Scoreboard_data[i].ID != ID) continue;
index = i;
break;
}
if(index == -1) return;
Scoreboard_data[i][key] = to;
if(sort_parameter)
Scoreboard_data[i][Format("%s_", key)] = sort_parameter;
Scoreboard->Update(ID);
}
// updates the display of the scoreboard
// there is usually no need to call it manually since Scoreboard->SetData calls Update
public func Update(
int ID /* ID of the entry to update */
, int index /* optional, internal index. leave at nil.*/
)
{
if(index == nil)
{
for(var i = 0; i < GetLength(Scoreboard_data); ++i)
{
if(Scoreboard_data[i].ID != ID) continue;
index = i;
break;
}
if(index == nil) return;
}
var data = Scoreboard_data[index];
// title - playername f.e.
SetScoreboardData(data.ID, Scoreboard_X_title, data.title, -1);
var len = GetLength(Scoreboard_keys);
for(var i = 0; i < len; ++i)
{
var col = Scoreboard_keys[i];
if(!col.key) continue;
if(col.key == "title") continue; // already set
// aquire value
var value = col.default;
if(data[col.key] != nil) value = data[col.key];
// get sorting parameter
var sort = data[Format("%s_", col.key)];
if(sort == nil)
if(GetType(value) == C4V_Int) sort = value;
// the column provides a conditional function
if(col.conditional)
{
value = col->conditional(value);
// overwrite old sort?
if(GetType(value) == C4V_Int) sort = value;
}
if(value == nil) value = "";
else if(GetType(value) == C4V_Int) {value = Format("%d", value);}
else if(GetType(value) == C4V_Def) value = Format("{{%i}}", value);
else if(GetType(value) == C4V_Bool) {sort = value; if(value) value = "X"; else value = "";}
SetScoreboardData(data.ID, col.index, value, sort);
}
// do sorting for fields neccessary
for(var i = len-1; i >= 0; --i)
{
var col = Scoreboard_keys[i];
if(!col.key) continue;
if(!col.sorted) continue;
SortScoreboard(col.index, col.desc);
}
}
// updates the whole scoreboard
public func UpdateAll()
{
// for every row, do update
var len = GetLength(Scoreboard_data);
for(var i = 0; i < len; ++i)
{
Scoreboard->Update(Scoreboard_data[i].ID, i);
}
}
// initializes the scoreboard with certain columns and attributes
// can be called multiple times and scales
// values must be an array of proplists where each entry stands for one column
// the entries can have the following attributes:
// "key" is required and used later for Scoreboard->SetData
// {key (string), priority (int), sorted (bool), desc (bool), title (string), default (any)}
// one row with key = "title" is necessary and will be automatically added if left out and not existent
public func Init(array values /* see description */)
{
// first call?
if(Scoreboard_unique_ids == nil)
{
Scoreboard_unique_ids = 0xffffff;
Scoreboard_keys = [];
Scoreboard_data = [];
if(!Scoreboard_title_set)
Scoreboard->SetTitle("Scoreboard");
}
// merge arrays
for(var val in values)
{
if(val == nil) continue;
var index = nil;
for(var i = GetLength(Scoreboard_keys)-1; i >= 0; --i)
{
if(Scoreboard_keys[i].key != val.key) continue;
index = i;
break;
}
if(index == nil)
PushBack(Scoreboard_keys, val); // new entry
else Scoreboard_keys[index] = val; // overwrite
}
// title property set?
var found_title = false;
for(var col in Scoreboard_keys)
{
if(col.key != "title") continue;
found_title = true;
break;
}
// if not, add
if(!found_title)
PushBack(Scoreboard_keys, {key = "title", title = ""});
// sort, selection sort
var len = GetLength(Scoreboard_keys);
for(var x = 0; x < len - 1; ++x)
{
var max = -1, max_val = nil;
for(var i = x; i < len; ++i)
{
var data = Scoreboard_keys[i];
if(max_val == nil || (data.priority > max_val))
{
max = i;
max_val = data.priority;
}
}
if(max == -1) break;
var t = Scoreboard_keys[x];
Scoreboard_keys[x] = Scoreboard_keys[max];
Scoreboard_keys[max] = t;
}
// assign indices to scoreboard data, they are now sorted - also create scoreboard
var len = GetLength(Scoreboard_keys);
for(var i = 0; i < len; ++i)
{
Scoreboard_keys[i].index = i;
if(Scoreboard_keys[i].key == "title") // title has special index and no headline
{
Scoreboard_keys[i].index = Scoreboard_X_title;
// don't set headline for title (first) column, because that would change the scoreboard title
continue;
}
// check title
if(GetType(Scoreboard_keys[i].title) == C4V_Def)
Scoreboard_keys[i].title = Format("{{%i}}", Scoreboard_keys[i].title);
var data = -0xffffff;
if(Scoreboard_keys[i].desc) data = 0xffffff;
SetScoreboardData(Scoreboard_Y_title, Scoreboard_keys[i].index, Scoreboard_keys[i].title, data);
}
// setup scoreboard
Scoreboard->UpdateAll();
// show scoreboard, only initially - after that it's the player's choice
DoScoreboardShow(1);
}
// sets the title of the scoreboard, standard is "Scoreboard"
public func SetTitle(string title)
{
SetScoreboardData(SBRD_Caption, SBRD_Caption, title);
Scoreboard_title_set = true;
}

View File

@ -88,11 +88,15 @@ protected func DoSwing(object clonk, int ix, int iy)
{
++iDist;
}
var x2 = Sin(180-angle,iDist);
var y2 = Cos(180-angle,iDist);
var is_solid = GBackSolid(x2,y2);
// alternatively hit certain objects
var target_obj = FindObject(Find_AtPoint(x2, y2), Find_Func("CanBeHitByPickaxe"));
if(GBackSolid(x2,y2))
if(is_solid || target_obj)
{
// Message("Hit %s", MaterialName(GetMaterial(x2,y2))); //for debug
@ -100,7 +104,7 @@ protected func DoSwing(object clonk, int ix, int iy)
var tex = GetTexture(x2,y2);
// special effects
if(GetMaterialVal("DigFree","Material",mat))
if(is_solid && GetMaterialVal("DigFree","Material",mat))
{
var clr = GetAverageTextureColor(tex);
var a = 80;
@ -113,7 +117,12 @@ protected func DoSwing(object clonk, int ix, int iy)
}
// dig out resources too! Don't just remove landscape pixels
BlastFree(GetX()+x2,GetY()+y2,5,GetController());
if(is_solid)
BlastFree(GetX()+x2,GetY()+y2,5,GetController());
// notify the object that it has been hit
if(target_obj)
target_obj->~OnHitByPickaxe(this, clonk);
}
}

View File

@ -206,6 +206,29 @@ public func StartLoad(object weapon)
aim_schedule_timer2 = aim_set["LoadTime2"];
aim_schedule_call2 = "DuringLoad";
}
var e = GetEffect("IntLoadingBar", this);
if(e)
{
RemoveEffect(nil, this, e);
}
e = AddEffect("IntLoadingBar", this, 1, BoundBy(aim_schedule_timer / 20, 3, 20), this);
e.max = aim_schedule_timer;
e.current = 0;
// handled by HUDAdapter to add a progress bar
this->~SetProgressBarLinkForObject(weapon, e);
}
func FxIntLoadingBarTimer(target, effect, time)
{
effect.current = time;
if(time > effect.max + 40) // the progress bar int he HUD should have updated by then
{
return -1;
}
return 1;
}
public func DuringLoad() { aim_weapon->~DuringLoad(this); }
@ -402,6 +425,9 @@ public func ApplySet(set)
public func ResetHands(bool pause)
{
if(!GetEffect("IntAimCheckProcedure", this))
return;
if(aim_weapon != nil)
{
aim_weapon->~Reset(this);
@ -420,6 +446,7 @@ public func ResetHands(bool pause)
SetBackwardsSpeed(nil);
RemoveEffect("IntAim", this);
RemoveEffect("IntLoadingBar", this);
SetTurnForced(-1);
@ -430,7 +457,12 @@ public func ResetHands(bool pause)
{
aim_weapon = nil;
aim_set = nil;
aim_schedule_call = nil;
aim_schedule_timer = nil;
aim_schedule_call2 = nil;
aim_schedule_timer2 = nil;
RemoveEffect("IntAimCheckProcedure", this);
}
}

View File

@ -140,10 +140,13 @@ public func SetHandItemPos(int hand, int inv)
use_objects[hand] = inv;
// additional callbacks
if(GetHandItem(hand2))
var hand_item;
if(hand_item = GetHandItem(hand2))
{
this->~OnSlotFull(hand2);
GetHandItem(hand2)->~Selection(this, hand2);
// OnSlotFull might have done something to the item
if(GetHandItem(hand2) == hand_item)
hand_item->~Selection(this, hand2);
}
else
this->~OnSlotEmpty(hand2);
@ -152,10 +155,13 @@ public func SetHandItemPos(int hand, int inv)
use_objects[hand] = inv;
// call callbacks
if(GetItem(inv))
var item;
if(item = GetItem(inv))
{
this->~OnSlotFull(hand);
GetItem(inv)->~Selection(this, hand);
// OnSlotFull might have done something to the item
if(GetItem(inv) == item)
GetItem(inv)->~Selection(this, hand);
}
else
{
@ -380,7 +386,9 @@ protected func Collection2(object obj)
if(handpos != nil)
{
this->~OnSlotFull(handpos);
obj->~Selection(this, handpos);
// OnSlotFull might have done something to obj
if(GetHandItem(handpos) == obj)
obj->~Selection(this, handpos);
}
}
@ -476,7 +484,9 @@ protected func Ejection(object obj)
if(handpos != nil)
{
this->~OnSlotFull(handpos);
o->~Selection(this, handpos);
// OnSlotFull might have done something to o
if(GetHandItem(handpos) == o)
o->~Selection(this, handpos);
}
break;
@ -775,7 +785,8 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
CreateContentsMenus();
// CreateContentsMenus calls SetMenu(this) in the clonk
// so after this call menu = the created menu
GetMenu()->Show();
if(GetMenu())
GetMenu()->Show();
return true;
}

View File

@ -14,7 +14,7 @@ local constructinfo_shown;
@param producer the producer for which to create the production menu.
@return a pointer to the created menu, or \c nil if failed.
*/
global func CreateConstructionMenu(object constructor)
global func CreateConstructionMenu(object constructor, bool create_at_mouse_pos)
{
// Safety checks.
if (!this) return;
@ -27,6 +27,13 @@ global func CreateConstructionMenu(object constructor)
this->SetMenu(controller);
controller->SetCommander(constructor);
if(create_at_mouse_pos)
{
var xy = GetPlayerCursorPos(constructor->GetOwner());
if(xy)
controller->SetPosition(xy[0],xy[1],true);
}
// Add all possible structures to the menu.
controller->AddMenuStructures(constructor, this);

View File

@ -30,7 +30,7 @@ public func ControlUseStart(object clonk, int x, int y)
}
// Otherwise create a menu with possible structures to build.
clonk->CreateConstructionMenu(this);
clonk->CreateConstructionMenu(this, true);
clonk->CancelUse();
return true;
}

View File

@ -20,13 +20,18 @@ public func Initialize()
{
this.Plane=1545;
fade = 0;
color = GetPlayerColor(GetOwner());
SetClrModulation(color|RGBa(0,0,0,fade));
SetAction("Fly");
SetComDir(COMD_None);
ResetColor();
return true;
}
func ResetColor()
{
color = GetPlayerColor(GetOwner());
SetClrModulation(color|RGBa(0,0,0,fade));
}
func MoveTo(int x, int y, int r)
{
if(GetEffect("MoveTo", this)) RemoveEffect("MoveTo", this);

View File

@ -127,6 +127,18 @@ func RedrawFlagRadius()
lflag.range_markers[marker_index] = marker;
}
// there were unnecessary markers?
if(marker_index < GetLength(lflag.range_markers) - 1)
{
var old = marker_index;
while(++marker_index < GetLength(lflag.range_markers))
{
var marker = lflag.range_markers[marker_index];
marker->RemoveObject();
lflag.range_markers[marker_index] = nil;
}
SetLength(lflag.range_markers, old + 1);
}
}
func RefreshOwnershipOfSurrounding()
@ -339,6 +351,18 @@ public func SetFlagRadius(int to)
return true;
}
// reassign owner of flag markers for correct color
func OnOwnerChange(old)
{
var new_owner = GetOwner();
for(var marker in lflag.range_markers)
{
if(!marker) continue;
marker->SetOwner(new_owner);
marker->ResetColor();
}
}
public func GetFlagRadius(){return lflag.radius;}
public func GetFlagConstructionTime() {return lflag.construction_time;}
public func GetFlagMarkerID(){return LibraryFlag_Marker;}

View File

@ -143,6 +143,14 @@ protected func OnSlotEmpty(int slot)
return _inherited(slot, ...);
}
// used to add a progress bar to an inventory slot
// "effect" refers to an effect with the properties "max" and "current" that is used to keep the progress bar state up-to-date
func SetProgressBarLinkForObject(object what, proplist effect)
{
if(HUDcontroller)
HUDcontroller->SetProgressBarLinkForObject(what, effect);
return _inherited(what, effect, ...);
}
protected func OnHandSelectionChange(int old, int new, int handslot)
{

View File

@ -57,11 +57,7 @@ func AddPowerConsumer(object p, int a)
// message
var diff = 0;
{
var t = CreateObject(FloatingMessage, o.obj->GetX() - GetX(), o.obj->GetY() - GetY(), NO_OWNER);
t->SetMessage(Format("%d</c>{{Library_PowerConsumer}}", diff));
t->SetColor(255, 0, 0);
t->SetYDir(-10);
t->FadeOut(4, 8);
VisualizePowerChange(o.obj, 0, o.amount, false);
}
o.obj->~OnRemovedFromPowerSleepingQueue();
@ -109,10 +105,10 @@ func AddPowerLink(object p, int a, bool surpress_balance_check)
diff = a - o.amount;
power_balance += diff;
before = power_links[i].amount;
if(a == 0)
{
before = power_links[i].amount;
power_links[i] = nil;
}
else power_links[i] = n;
@ -133,22 +129,13 @@ func AddPowerLink(object p, int a, bool surpress_balance_check)
power_balance += diff;
}
diff = n.amount;
if((diff > 0) || ((a == 0) && (before > 0)))
if((n.amount > 0) || ((n.amount == 0) && (before > 0)))
{
var t = CreateObject(FloatingMessage, n.obj->GetX() - GetX(), n.obj->GetY() - GetY(), NO_OWNER);
t->SetMessage(Format("+%d</c>{{Library_PowerConsumer}}", diff));
t->SetColor(0, 255, 0);
t->SetYDir(-10);
t->FadeOut(4, 8);
VisualizePowerChange(n.obj, n.amount, before, false);
}
else if((diff < 0) || ((a == 0) && (before < 0)))
else if((n.amount < 0) || ((n.amount == 0) && (before < 0)))
{
var t = CreateObject(FloatingMessage, n.obj->GetX() - GetX(), n.obj->GetY() - GetY(), NO_OWNER);
t->SetMessage(Format("%d</c>{{Library_PowerConsumer}}", diff));
t->SetColor(255, 0, 0);
t->SetYDir(-10);
t->FadeOut(4, 8);
VisualizePowerChange(n.obj, n.amount, before, false);
}
if(n.amount < 0)
n.obj->~OnEnoughPower(); // might be reverted soon, though
@ -276,6 +263,7 @@ func SleepLink(int index)
// sadly not enough power anymore
o.obj->~OnNotEnoughPower();
VisualizePowerChange(o.obj, 0, o.amount, true);
return true;
}
@ -323,6 +311,55 @@ public func Init()
Library_Power_power_compounds = [];
}
// static
func VisualizePowerChange(object obj, int to, int before, bool loss)
{
var e = GetEffect("VisualPowerChange", obj);
if(!e)
e = AddEffect("VisualPowerChange", obj, 1, 5, nil, Library_Power);
var to_abs = Abs(to);
var before_abs = Abs(before);
e.max = Max(to_abs, before_abs);
e.current = before_abs;
e.to = to_abs;
if(before > 0 && to < 0) {e.color = RGB(1, 255, 1); e.back_color = RGB(100, 100, 1);}
else if(before < 0 && to > 0){e.color = RGB(1, 255, 1); e.back_color = RGBa(1, 100, 1);}
else if(to < 0){e.color = RGB(1, 255, 1); e.back_color = RGB(255, 1, 1);}
else if(to > 0) {e.color = RGB(1, 255, 1); e.back_color = RGBa(10, 10, 10, 150);}
EffectCall(obj, e, "Refresh");
}
func FxVisualPowerChangeRefresh(target, effect)
{
if(effect.bar) effect.bar->Close();
var vis = VIS_Allies | VIS_Owner;
var controller = target->GetController();
if(controller == NO_OWNER) vis = VIS_All;
var off_x = -(target->GetDefCoreVal("Width", "DefCore") * 3) / 8;
var off_y = target->GetDefCoreVal("Height", "DefCore") / 2 - 10;
effect.bar = target->CreateProgressBar(GUI_BarProgressBar, effect.max, effect.current, 35
, controller, {x = off_x, y = off_y}, vis
, {size = 1000, bars = effect.max / 25, color = effect.color, back_color = effect.back_color});
}
func FxVisualPowerChangeTimer(target, effect, time)
{
if(!effect.bar) return -1;
if(effect.current == effect.to) return 1;
if(effect.to < effect.current) effect.current = Max(effect.current - 15, effect.to);
else effect.current = Min(effect.current + 15, effect.to);
effect.bar->SetValue(effect.current);
return 1;
}
// static
func GetPowerHelperForObject(object who)
{

View File

@ -15,21 +15,31 @@ local score_death_list; // Here the death count of all players is stored, access
/*-- Callbacks --*/
// called by the scoreboard, assigns a symbol to the scoreboard field
// used by Scoreboard_Relaunch too
public func ScoreboardCondition(int x)
{
if(x == -1) return Rule_KillLogs;
return x;
}
protected func Initialize()
{
// Make sure it is a list.
score_death_list = [];
// Set scoreboard death count caption.
SetScoreboardData(SBRD_Caption, GetDeathCol(), "{{Scoreboard_Death}}", SBRD_Caption);
// init scoreboard
Scoreboard->Init(
[{key = "deaths", title = Scoreboard_Death, sorted = true, desc = true, default = 0, priority = 75, conditional = Scoreboard_Death.ScoreboardCondition}]
);
return _inherited(...);
}
protected func InitializePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Create scoreboard death count entry for this player.
// Create scoreboard entry for this player, will only do it once
score_death_list[plrid] = 0;
SetScoreboardData(plrid, GetDeathCol(), Format("%d", score_death_list[plrid]), score_death_list[plrid]);
Scoreboard->NewPlayerEntry(plr);
return _inherited(plr, ...);
}
@ -38,15 +48,12 @@ protected func RelaunchPlayer(int plr, int killer)
var plrid = GetPlayerID(plr);
// Modify scoreboard death count entry for this player.
score_death_list[plrid]++;
SetScoreboardData(plrid, GetDeathCol(), Format("%d", score_death_list[plrid]), score_death_list[plrid]);
Scoreboard->SetPlayerData(plr, "deaths", score_death_list[plrid]);
return _inherited(plr, killer, ...);
}
protected func RemovePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Clear scoreboard death count entry for this player.
SetScoreboardData(plrid, GetDeathCol(), nil, nil);
return _inherited(plr, ...);
}
@ -56,6 +63,7 @@ public func SetDeathCount(int plr)
{
var plrid = GetPlayerID(plr);
score_death_list[plrid] = 0;
Scoreboard->SetPlayerData(plr, "deaths", score_death_list[plrid]);
return;
}
@ -65,10 +73,4 @@ public func GetDeathCount(int plr)
return score_death_list[plrid];
}
public func GetDeathCol()
{
//return ScoreboardCol(Scoreboard_Death);
return 101;
}
local Name = "Scoreboard Deaths";

View File

@ -19,17 +19,19 @@ protected func Initialize()
{
// Make sure it is a list.
score_kill_list = [];
// Set scoreboard kill count caption.
SetScoreboardData(SBRD_Caption, GetKillCol(), "{{Scoreboard_Kill}}", SBRD_Caption);
// init scoreboard
Scoreboard->Init(
[{key = "kills", title = Scoreboard_Kill, sorted = true, desc = true, default = 0, priority = 50}]
);
return _inherited(...);
}
protected func InitializePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Create scoreboard kill count entry for this player.
// init scoreboard for player
score_kill_list[plrid] = 0;
SetScoreboardData(plrid, GetKillCol(), Format("%d", score_kill_list[plrid]), score_kill_list[plrid]);
Scoreboard->NewPlayerEntry(plr);
return _inherited(plr, ...);
}
@ -44,15 +46,12 @@ protected func RelaunchPlayer(int plr, int killer)
return _inherited(plr, killer, ...);
// Modify scoreboard kill count entry for killer.
score_kill_list[plrid]++;
SetScoreboardData(plrid, GetKillCol(), Format("%d", score_kill_list[plrid]), score_kill_list[plrid]);
Scoreboard->SetPlayerData(killer, "kills", score_kill_list[plrid]);
return _inherited(plr, killer, ...);
}
protected func RemovePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Clear scoreboard kill count entry for this player.
SetScoreboardData(plrid, GetKillCol(), nil, nil);
return _inherited(plr, ...);
}
@ -62,6 +61,7 @@ public func SetKillCount(int plr, int value)
{
var plrid = GetPlayerID(plr);
score_kill_list[plrid] = value;
Scoreboard->SetPlayerData(plr, "kills", score_kill_list[plrid]);
return;
}
@ -75,13 +75,8 @@ public func DoKillCount(int plr, int value)
{
var plrid = GetPlayerID(plr);
score_kill_list[plrid] += value;
Scoreboard->SetPlayerData(plr, "kills", score_kill_list[plrid]);
return;
}
public func GetKillCol()
{
//return ScoreboardCol(Scoreboard_Kill);
return 107;
}
local Name = "Scoreboard Kills";

View File

@ -19,17 +19,19 @@ protected func Initialize()
{
// Make sure it is a list.
score_killstreak_list = [];
// Set scoreboard kill streak count caption.
SetScoreboardData(SBRD_Caption, GetKillStreakCol(), "{{Scoreboard_KillStreak}}", SBRD_Caption);
// init scoreboard
Scoreboard->Init(
[{key = "killstreaks", title = Scoreboard_KillStreak, sorted = true, desc = true, default = "", priority = 20}]
);
return _inherited(...);
}
protected func InitializePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Create scoreboard kill streak count entry for this player.
// make scoreboard entry for player
score_killstreak_list[plrid] = 0;
SetScoreboardData(plrid, GetKillStreakCol(), Format("%d", score_killstreak_list[plrid]), score_killstreak_list[plrid]);
Scoreboard->NewPlayerEntry(plr);
return _inherited(plr, ...);
}
@ -37,10 +39,10 @@ protected func RelaunchPlayer(int plr, int killer)
{
var plrid = GetPlayerID(plr);
var killerid = GetPlayerID(killer);
// Modify scoreboard kill streak count entry for killed player.
// reset scoreboard kill streak count entry for killed player.
score_killstreak_list[plrid] = 0;
SetScoreboardData(plrid, GetKillStreakCol(), Format("%d", score_killstreak_list[plrid]), score_killstreak_list[plrid]);
// Only if killer exists and has not committed suicide.
Scoreboard->SetPlayerData(plr, "killstreaks", nil);
// Only if killer exists and has not committed suicide.
if (plr == killer || !GetPlayerName(killer))
return _inherited(plr, killer, ...);
// Only if killer and victim are on different teams.
@ -48,15 +50,12 @@ protected func RelaunchPlayer(int plr, int killer)
return _inherited(plr, killer, ...);
// Modify scoreboard kill streak count entry for killer.
score_killstreak_list[killerid]++;
SetScoreboardData(killerid, GetKillStreakCol(), Format("%d", score_killstreak_list[killerid]), score_killstreak_list[killerid]);
Scoreboard->SetPlayerData(killer, "killstreaks", score_killstreak_list[killerid]);
return _inherited(plr, killer, ...);
}
protected func RemovePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Clear scoreboard kill streak count entry for this player.
SetScoreboardData(plrid, GetKillStreakCol(), nil, nil);
return _inherited(plr, ...);
}
@ -66,6 +65,7 @@ public func SetKillStreakCount(int plr, int value)
{
var plrid = GetPlayerID(plr);
score_killstreak_list[plrid] = value;
Scoreboard->SetPlayerData(plr, "killstreaks", score_killstreak_list[plrid]);
return;
}
@ -79,13 +79,8 @@ public func DoKillStreakCount(int plr, int value)
{
var plrid = GetPlayerID(plr);
score_killstreak_list[plrid] += value;
Scoreboard->SetPlayerData(plr, "killstreaks", score_killstreak_list[plrid]);
return;
}
public func GetKillStreakCol()
{
//return ScoreboardCol(Scoreboard_KillStreak);
return 109;
}
local Name = "Scoreboard Kill streaks";

View File

@ -1,8 +0,0 @@
[DefCore]
id=Scoreboard_Player
Version=5,2,0,1
Category=C4D_StaticBack|C4D_Rule
Picture=0,0,128,128
Width=128
Height=128
Offset=-64,-64

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,41 +0,0 @@
/*--
Modular scoreboard: Players
Author: Maikel
This script can be included to create a player column in the scoreboard.
Make sure that the following functions return _inherited(...);
* Initialize();
* InitializePlayer(int plr);
* RelaunchPlayer(int plr, int killer);
* RemovePlayer(int plr);
--*/
/*-- Callbacks --*/
protected func Initialize()
{
// Set general scoreboard caption.
SetScoreboardData(SBRD_Caption, SBRD_Caption, "Scoreboard", SBRD_Caption);
return _inherited(...);
}
protected func InitializePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Create scoreboard player entry for this player (its name).
SetScoreboardData(plrid, SBRD_Caption, GetTaggedPlayerName(plr), plrid);
return _inherited(plr, ...);
}
protected func RemovePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Clear scoreboard player entry for this player.
SetScoreboardData(plrid, SBRD_Caption, nil, nil);
return _inherited(plr, ...);
}
/*-- Misc --*/
local Name = "Scoreboard Players";

View File

@ -13,23 +13,33 @@
local score_relaunch_list; // Here the relaunch count of all players is stored, access through plrid.
// Overload this.
public func RelaunchCount()
{
return 5;
}
/*-- Callbacks --*/
protected func Initialize()
{
// Make sure it is a list.
score_relaunch_list = [];
// Set scoreboard relaunch count caption.
SetScoreboardData(SBRD_Caption, GetRelaunchCol(), "{{Scoreboard_Relaunch}}", SBRD_Caption);
// init scoreboard
// init scoreboard, uses the condition of Scoreboard_Deaths too
Scoreboard->Init(
[{key = "relaunches", title = Scoreboard_Relaunch, sorted = true, desc = true, default = "", priority = 75, conditional = Scoreboard_Death.ScoreboardCondition}]
);
return _inherited(...);
}
protected func InitializePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Create scoreboard relaunch count entry for this player.
// create scoreboard entry
score_relaunch_list[plrid] = RelaunchCount();
SetScoreboardData(plrid, GetRelaunchCol(), Format("%d", score_relaunch_list[plrid]), score_relaunch_list[plrid]);
Scoreboard->NewPlayerEntry(plr);
Scoreboard->SetPlayerData(plr, "relaunches", score_relaunch_list[plrid]);
return _inherited(plr, ...);
}
@ -38,15 +48,12 @@ protected func RelaunchPlayer(int plr, int killer)
var plrid = GetPlayerID(plr);
// Modify scoreboard relaunch count entry for this player.
score_relaunch_list[plrid]--;
SetScoreboardData(plrid, GetRelaunchCol(), Format("%d", score_relaunch_list[plrid]), score_relaunch_list[plrid]);
Scoreboard->SetPlayerData(plr, "relaunches", score_relaunch_list[plrid]);
return _inherited(plr, killer, ...);
}
protected func RemovePlayer(int plr)
{
var plrid = GetPlayerID(plr);
// Clear scoreboard relaunch count entry for this player.
SetScoreboardData(plrid, GetRelaunchCol(), nil, nil);
return _inherited(plr, ...);
}
@ -56,6 +63,7 @@ public func SetRelaunchCount(int plr, int value)
{
var plrid = GetPlayerID(plr);
score_relaunch_list[plrid] = value;
Scoreboard->SetPlayerData(plr, "relaunches", score_relaunch_list[plrid]);
return;
}
@ -69,19 +77,8 @@ public func DoRelaunchCount(int plr, int value)
{
var plrid = GetPlayerID(plr);
score_relaunch_list[plrid] += value;
Scoreboard->SetPlayerData(plr, "relaunches", score_relaunch_list[plrid]);
return;
}
public func GetRelaunchCol()
{
//return ScoreboardCol(Scoreboard_Relaunch);
return 103;
}
// Overload this.
public func RelaunchCount()
{
return 5;
}
local Name = "Scoreboard Relaunches";

View File

@ -23,6 +23,9 @@ func OnClonkDeath(object clonk, int killed_by)
return _inherited(clonk, killed_by, ...);
}
// parameters: clonk, owner, killed_by
global func GetAdditionalPlayerRelaunchString(){return _inherited(...);} // dummy
func OnClonkDeathEx(object clonk, int plr, int killed_by)
{
if(!GetPlayerName(plr)) return;
@ -82,6 +85,11 @@ func OnClonkDeathEx(object clonk, int plr, int killed_by)
log=Format("%s %s", log, other);
}
// also allow global callback function to add to death messages
other = GetAdditionalPlayerRelaunchString(clonk, plr, killed_by);
if(other)
log = Format("%s, %s", log, other);
Log(log);
}

View File

@ -127,7 +127,7 @@ func LoseCombination()
{
partner = nil;
slave = false;
if (case) case->LoseCombination();
if (case) case->LoseConnection();
}
// Called by our case because the case has a timer anyway

View File

@ -65,6 +65,25 @@ func CheckForEnemies()
return true;
}
// removes a timer from an object that was added earlier with AddTimer. This removes exactly one timer that fits to the name and returns true on success
global func RemoveTimer(string function /* name of the timer to remove */)
{
if(!this)
return false;
var effect, index = 0;
while(effect = GetEffect("IntScheduleCall", this, index++))
{
if(effect.Function != function) continue;
if(effect.NoStop != true) continue;
RemoveEffect(nil, this, effect);
return true;
}
// not found
return false;
}
// Executes a function repetitively with delay.
global func ScheduleCall(object obj, string function, int interval, int repeats, par0, par1, par2, par3, par4)
{

View File

@ -14,7 +14,7 @@ MsgTutScale=Hier musst du an der Wand hochklettern, um weiterzukommen. Dein Clon
MsgTutHangle=Um zu hangeln, springe einfach an die Decke. Dann kannst du normal nach links oder rechts hangeln. Um schließlich loszulassen, drücke [S].
MsgTutSwim=Im Wasser kannst du in jede Richtung schwimmen. Wenn du untertauchst, hält dein Clonk den Atem an. Pass auf, rechtzeitig wieder aufzutauchen, sonst ertringt er.
MsgTutDig=Hier brauchst du eine Schaufel um hindurchzugraben. Was ist das da unter Wasser?
MsgTutTools=Das Inventar deines Clonks in der unteren linken Bildschirmecke zeigt nun die Schaufel. Ist sie in der linken Hand (linker Slot), benutzt du sie mit der linken Maustaste. Ist sie in der rechten Hand (rechter Slot), mit der rechten Maustaste.||Ein Klick mit der rechten Maustaste auf die Schaufel im Inventar zeigt eine kurze Beschreibung an, wie sie funktioniert.
MsgTutChest=Um hier weiterzukommen, musst du eine Lehmbrücke bauen. In der Truhe ist ein Lehmklumpen. Stell dich vor die Truhe und drücke die [E], um das Inventarmenü zu öffnen. Sobald der Inhalt der Truhe angezeigt wird, kannst du ihn in dein Inventar holen. || Wenn du ein Objekt aus deinem Rucksack holen möchtest, drück [Q]. Mit Rechts- oder Linksklick kannst du nun ein Objekt in die entsprechende Hand nehmen. Mit [Q] lässt sich das Menü schließen.
MsgTutTools=Das Inventar deines Clonks am linken Bildschirmrand zeigt nun die Schaufel. Dieses hat mehrere Slots, zwei davon können als aktiv markiert werden. Mit der linken Maustaste weist du den Slot der linken Hand zu; mit der rechten Maustaste der rechten Hand.||Wenn du mit der Maus über die Schaufel im Inventar fährst, wird eine eine kurze Beschreibung angezeigt, die erklärt wie sie funktioniert.
MsgTutChest=Um hier weiterzukommen, musst du eine Lehmbrücke bauen. In der Truhe ist ein Lehmklumpen. Stell dich vor die Truhe und drücke [E], um das Inventarmenü zu öffnen. Um den Lehmklumpen dann einzusammeln, klicke im Menü darauf oder ziehe ihn in den Kreis vom Clonk. Drücke nochmal [E] um das Menü wieder zu schließen.
MsgTutLoam=Um eine Lehmbrücke zu bauen, halte die Maustaste gedrückt. Die Konstruktion funktioniert wie das Graben, nur statt einem Tunnel wird eine Lehmbrücke gebaut.
MsgTutFlint=Oh, was ist das? Der Höhlenausgang ist durch solides Gestein versperrt. Mit der Schaufel kommst du da nicht durch.|In der Truhe sind Feuersteine, die bei Aufprall explodieren. Hole sie dir und wirf sie auf die Felswand, um dir einen Weg freizusprengen (ziele und werfe mit der Maus). Wenn du beide einsammeln willst, könntest du die Schaufel vorher in deinen Rucksack tun.||Erinnerung: Drücke [Q], um deinen Rucksack zu öffnen.
MsgTutFlint=Oh! was ist das? Der Höhlenausgang ist durch solides Gestein versperrt. Mit der Schaufel kommst du da nicht durch.|In der Truhe sind Feuersteine, die bei Aufprall explodieren. Hole sie dir und wirf sie auf die Felswand, um dir einen Weg freizusprengen (ziele und werfe mit der Maus).

View File

@ -7,14 +7,14 @@ MsgRepeatRoundDesc=Restart this scenario.
# Tutorial messages
MsgTutIntro0=Welcome to OpenClonk!
MsgTutIntro1=This is your clonk.
MsgTutIntro2=Travel through the cave to the right to complete the tutorial, your current goal is always shown in the upper right corner of the screen.
MsgTutIntro2=Travel through the cave to the right to complete the tutorial. Your current goal is always shown in the upper right corner of the screen.
MsgTutIntro3=If at any time you need help, click on my icon in the upper right corner of the screen. Once you're done reading, click again on the icon to hide the message.
MsgTutMovement=Clonks are controlled with the WASD keys. Press [A] or [D] to make the clonk walk left or right. Pressing [W] will make the clonk jump.
MsgTutScale=Here you will need to scale the wall to advance. To scale, walk towards the wall until your clonk grabs on. Once you have grabbed on, you may scale up or down the wall by holding [W] or [S].
MsgTutHangle=To hangle, jump towards the ceiling. When your clonk grabs on, you will be able to move left or right. To release, press [S].
MsgTutSwim=Swimming is controlled simply by pressing in the direction you wish your clonk to move. While underwater make certain you resurface before your breath runs out, otherwise you will drown!
MsgTutDig=You'll need a shovel to dig through here. What's that under the water?
MsgTutTools=The shovel is now shown in your clonk's inventory on the lower left of the screen. You can use it with the left mouse button if it is in your left hand (left slot) and with the right mouse button if it is in your right hand (right slot). || Right click on the shovel in your inventory slot to get a brief description on how it works.
MsgTutChest=You'll need to make a loam bridge to cross this obstacle. In the chest there is a chunk of loam. Go in front of the chest and press [E] to open the inventory menu. Once the chest's contents appear, you can click the left or right mouse button to collect items into your inventory.||If you want to get items from your bagpack, press [Q]. Either right or left click an item, and it will be swapped with whatever you have in that hand. Press [Q] again to close the menu.
MsgTutTools=The shovel is now shown in your clonk's inventory on the left side of the screen. It has several slots, of which two can be selected as active. Left-clicking assigns the slot to the left hand; right-clicking, to the right. To use a item, simply click the corresponding button.||Place the mouse over the shovel in your inventory slot to get a brief description on how it works.
MsgTutChest=You'll need to make a loam bridge to cross this obstacle. In the chest there is a chunk of loam. Go in front of the chest and press [E] to open the contents-menu. It will show the contents of the clonk's inventory and the chest. In this menu, click on the chunk of loam or drag it into the clonk's circle to collect it.||Press [E] again to close the menu.
MsgTutLoam=Hold down the mouse button to build a loam bridge. Building a loam bridge works like digging with the shovel, only that you don't dig a tunnel but build a bridge out of loam.
MsgTutFlint=Oh, what's this? The cave's exit has been blocked with solid rock. You can't dig through solid rock with the shovel. In the chest are firestones which explode on impact. Collect them and throw them onto the wall to blow a hole into it (aim and throw with the mouse). To collect both, you'll want to put your shovel into your backpack.||Reminder: To access your backpack, press [Q].
MsgTutFlint=Oh! What's this? The cave's exit has been blocked with solid rock. You can't dig through solid rock with the shovel. In the chest are firestones which explode on impact. Collect them and throw them at the wall to blow a hole into it (aim and throw with the mouse).

View File

@ -7,16 +7,15 @@ MsgRepeatRoundDesc=Diese Runde wiederholen.
# Tutorial messages
MsgTutWelcome=Willkommen zur zweiten Lernrunde. In dieser Lernrunde hast Du zwei Clonks zur Verfügung. Das Spielziel dieser Runde ist wieder, den Fahnenmast am rechten Rand der Karte zu erreichen, diesmal aber mit beiden Clonks. Klicke auf mein Bildchen in der oberen linken Ecke des Bildschirmes für Tipps. Du kannst jederzeit mit dem Mausrad oder mit F5/F6 zoomen.
MsgTutGrappleUp=Der Clonk kann nicht hoch genug springen, um über die Klippe zu kommen. Ziele und schieße mit dem Enterhaken in deinem Inventar an die angezeigte Position. Du kannst mit [W] und [S] das Seil hoch- und runterklettern sowie mit [A] und [D] hin- und herschaukeln.
MsgTutCrewSelection=Es gibt momentan nichts mehr was du mit diesem Clonk machen kannst. Um ein anderes Crewmitglied anzuwählen, klicke entweder auf das Bildchen des Clonks in der linken oberen Ecke des Bildschirms, drücke [Shift] + die Nummer des auszuwählenden Clonks oder wähle den nächsten Clonk an indem du [R] oder [T] drückst.
MsgTutCrewSelection=Es gibt momentan nichts mehr was du mit diesem Clonk machen kannst. Um ein anderes Crewmitglied anzuwählen, klicke entweder auf das Bildchen des Clonks in der linken oberen Ecke des Bildschirms, drücke [Strg] + die Nummer des auszuwählenden Clonks oder wähle den nächsten Clonk an indem du [R] oder [T] drückst.
MsgTutBlowUpGold=Sieht aus, als hätten Bergarbeiter einen verdrahteten Zünder in dieser Goldmine zurückgelassen. Sammle ihn auf und drücke [Benutzen], um das Gold, dass deinen Weg versperrt, wegzusprengen.
MsgTutFreeOtherClonk=Jetzt wo sich dein Clonk freigesprengt hat, versuche einen Weg zu finden, wie du deinen anderen Clonk befreien kannst. Denk daran, dass dein Clonk mit vielen Dingen interagieren kann, die in der Landschaft herumstehen. Du kannst sie benutzen, indem du dich vor sie stellst und [Interagieren] (Leertaste) drückst. Objekte, mit denen dein Clonk interagieren kann, tauchen auch wie die Truhe als Bildchen unten am Bildschirmrand auf.
MsgTutCannon=Ah, du hast die Kanone gefunden. Mit der Kanone kann man Objekte über große Distanzen verschießen. Dazu brauchst du allerdings ein Pulverfass. Um ein Gegenstand mit der Kanone zu verschießen, fasse die Kanone mit der Leertaste an und halte die Maustaste gedrückt, um zu zielen. Mit der linken Maustaste verschießt du, was du in der linken Hand hast und mit der rechten Maustaste, was du in der rechten Hand hast.
MsgTutExplosivesChest=Die Bergarbeiter haben einige Sprengstoffe in der Truhe zurückgelassen. Stell dich vor die Truhe und drücke die [Leertaste], um die Truhe zu öffnen. Sobald der Inhalt der Truhe angezeigt wird, kannst du ihn in die Hand nehmen. || Wählst du den Feuerstein mit der linken Maustaste aus, nimmst du ihn in die linke Hand. Wählst du ihn mit der rechten Maustaste aus, nimmst du ihn in die rechte Hand.
MsgTutFireCannon=Du musst dich durch den Fels dort sprengen, um deinen anderen Clonk zu befreien. Suche nach einigen Feuersteinen in der Goldmine.
MsgTutCannon=Ah, du hast die Kanone gefunden. Mit der Kanone kann man Objekte über große Distanzen verschießen. Dazu brauchst du allerdings ein Pulverfass.
MsgTutExplosivesChest=Die Bergarbeiter haben einige Sprengstoffe in der Truhe zurückgelassen. Stell dich vor die Truhe und drücke die [Leertaste], um die Truhe zu öffnen. Sobald der Inhalt der Truhe angezeigt wird, kannst du ihn in die Hand nehmen.
MsgTutFireCannon=Um ein Gegenstand mit der Kanone zu verschießen, fasse die Kanone mit der Leertaste an und halte die Maustaste gedrückt, um zu zielen. Mit der linken Maustaste verschießt du, was du in der linken Hand hast und mit der rechten Maustaste, was du in der rechten Hand hast. Du musst dich durch den Fels dort sprengen, um deinen anderen Clonk zu befreien. Suche nach einigen Feuersteinen in der Goldmine.
MsgTutGrappleSwing=Wähle jetzt deinen anderen Clonk aus und bewege ihn an den Rand zum Pfeil. Springe und schieße mit dem Enterhaken an die Decke, dort wo der andere Pfeil ist. Dann kannst Du dich mit [A] und [D] über den Abgrund schwingen.
MsgTutRopeladder=Gut gemacht! Jetzt kannst du deine Strickleiter benutzen um deinem Freund auf die Klippe zu helfen. Gehe zum Pfeil und lass die Strickleiter herab, indem du links neben deinen Clonk klickst. An Strickleitern kann man wie an normalen Wänden klettern.
MsgTutDive=Um am nächsten Hindernis vorbeizukommen, musst du tauchen. Clonks können nur begrenzt lange die Luft anhalten, deshalb musst du regelmäßig auftauchen. Du kannst an den Stellen Luft holen, die von den Pfeilen angezeigt werden. In den Truhen unter dem See findest du Sprengstoff, welchen du brachst, um das Lernrunde zu schaffen.
MsgTutBlastGranite=Benutze den Sprengstoff, den du unter dem See findest, um durch das Granit zu sprengen. Die beste Stelle wird vom Pfeil angezeigt.
MsgTutBlastedGranite=Gut gemacht! Um die letzte Hürde zu bestehen, brauchst du zwei Enterhaken pro Clonk. Diese findest du im Tunnel, wenn du ein Stück zurück gehst.
MsgTutLastGrapple=Oh oh, das sieht ja wie ein Säuresee aus. Du hast keine Chance hier unbeschadet hinüber zu schwimmen. Der einfachste Weg hinüber ist mit Hilfe der Enterhaken: Schieß den ersten Enterhaken an die Himmelsinsel und während du am ersten Seil hoch kletterst, kannst du den anderen Enterhaken benutzen, indem du ihn weiter vorne befestigst. Wiederhole das bis du den ganzen Säuresee überquert hast.
MsgTutBackpack=Wie du vielleicht bereits weißt, kann der Clonk zwei Gegenstände in seinen Händen halten. Allerdings kann er noch mehr in seinem Rucksack verstauen. Der Rucksack kann mit [Q] geöffnet/geschlossen werden. Wenn er offen ist, kannst du einen der Gegenstände im Rucksack mit einem der Gegenstände in deiner Hand austauschen. Linke Maustaste für linke Hand, rechte Maustaste für rechte Hand.
MsgTutLastGrapple=Oh oh, das sieht ja wie ein Säuresee aus. Du hast keine Chance hier unbeschadet hinüber zu schwimmen. Der einfachste Weg hinüber ist mit Hilfe der Enterhaken: Schieß den ersten Enterhaken an die Himmelsinsel und während du am ersten Seil hoch kletterst, kannst du den anderen Enterhaken benutzen, indem du ihn weiter vorne befestigst. Wiederhole das bis du den ganzen Säuresee überquert hast.

View File

@ -5,17 +5,17 @@ MsgRepeatRound=&Repeat this round
MsgRepeatRoundDesc=Restart this scenario.
# Tutorial messages
MsgTutWelcome=Welcome to the second tutorial. In this tutorial you have two clonks at your disposal, and your goal will be to reach the flag on the far right side with both clonks. At any time you can click on the guide for helpful hints, note that you can zoom in and out with F5/F6 or the mouse wheel.
MsgTutGrappleUp=The clonk is not able to jump that high, you can use the grappling hook in your inventory. Use the mouse to aim and shoot the hook into the rock at the indicated position. You can use [W] and [S] to climb the rope, and [A] and [D] to swing back and forth.
MsgTutCrewSelection=There is nothing else you can do with this clonk for the moment. To select another crew member you can either click on the clonk you want to control in the upper left part of the HUD, press [Shift] + the number key corresponding to the clonk, or cycle through your crew by pressing [R] or [T].
MsgTutWelcome=Welcome to the second tutorial. In this tutorial you have two clonks at your disposal, and your goal will be to reach the flag on the far right side with both clonks. At any time you can click on the guide for helpful hints; note that you can zoom in and out with F5/F6 or the mouse wheel.
MsgTutGrappleUp=The clonk is not able to jump that high; you can use the grappling hook in your inventory. Use the mouse to aim and shoot the hook into the rock at the indicated position. You can use [W] and [S] to climb the rope, and [A] and [D] to swing back and forth.
MsgTutCrewSelection=There is nothing else you can do with this clonk for the moment. To select another crew member you can either click on the clonk you want to control in the upper left corner of the screen, press [Ctrl] + the number key corresponding to the clonk, or cycle through your crew by pressing [R] or [T].
MsgTutBlowUpGold=It seems like miners left behind a wired detonator in this gold mine. Collect it and press [Use] to blow up the gold blocking your way out.
MsgTutFreeOtherClonk=Now that this clonk is free, look for a way to free your other clonk. Note that your clonk can interact with many objects, most of them vehicles and buildings. You can interact with them by standing in front of them and pressing [Interact] (Space bar), also for every interactable a clickable icon will appear in the HUD.
MsgTutCannon=Ah you found the cannon, the cannon can be used to fire objects over great distances. It needs gunpowder, contained in a powder keg, to operate. This can be found in the chest near the blasted gold.
MsgTutExplosivesChest=The miners left some explosives in this chest. Open it with [Interact], the chest's contents will then appear. Click the with left or right mouse button on an item to swap/collect it into your hands. To carry more items the clonk has a backpack, press [Q] to open it. The backpack works similar to the chest and you can swap items between the backpack and your hands.
MsgTutFireCannon=Good, you have brought some ammunition. To fire an object with the cannon click in the landscape to aim the cannon, left click will shoot your left-hand item, right click your right-hand item. You need to blast through the rock over there to free your other clonk.
MsgTutGrappleSwing=Now select your other clonk and move to the edge indicated by the arrow. Jump from there and shoot with the grappler to the granite ceiling, the other arrow. Then use [A] and [D] to swing across the cliff.
MsgTutRopeladder=Well done! You can now use your ropeladder to help your friend up this ledge. Move to the arrow and release the ropeladder by clicking to the left of your clonk. Ropeladders can be climbed just as normal walls.
MsgTutDive=To make it past the next obstacle you would need to dive. Clonks have limited breath, so you need to resurface regularly. You can resurface at the locations indicated by the arrows. In the chests under the lake explosives can be found, these are crucial for completing the tutorial.
MsgTutFreeOtherClonk=Now that this clonk is free, look for a way to free your other clonk. Note that your clonk can interact with many objects, most of them containers, vehicles and buildings. You can interact with them by standing in front of them and pressing [Interact] (Space bar); also for every interactable, a clickable icon will appear on the lower side of the screen.
MsgTutCannon=Ah! You found the cannon; it can be used to fire objects over great distances. It needs gunpowder, contained in a powder keg, to operate. This can be found in the chest near the blasted gold.
MsgTutExplosivesChest=The miners left some explosives in this chest. Open it with [Interact]; the chest's contents will then appear. Click on an item to collect it into your inventory.
MsgTutFireCannon=Good! You have brought some ammunition. To fire an object with the cannon, click in the landscape to aim the cannon. Left click will shoot your left-hand item, right click your right-hand one. You need to blast through the rock over there to free your other clonk.
MsgTutGrappleSwing=Now, select your other clonk and move to the edge indicated by the arrow. Jump from there and shoot with the grappler to the granite ceiling, the other arrow. Then, use [A] and [D] to swing across the cliff.
MsgTutRopeladder=Well done! You can now use your rope ladder to help your friend up to get on this ledge. Move to the arrow and release the rope ladder by clicking to the left of your clonk. Rope ladders can be climbed just as normal walls.
MsgTutDive=To make it past the next obstacle you would need to dive. Clonks have limited breath, so you need to resurface regularly. You can resurface at the locations indicated by the arrows. In the chests under the lake explosives can be found; these are crucial for completing the tutorial.
MsgTutBlastGranite=Use the explosives, which can be found under the lake, to blast through the granite. The best location is indicated by the arrow.
MsgTutBlastedGranite=Good job, for the last hurdle you need some grapple bows. Two per clonk to be precise, these can be found a tunnel a little back.
MsgTutLastGrapple=Ouch, that looks like an acid lake. No chance swimming across here, the easiest way over is by alternate use of two grapple bows. Shoot the first hook into the granite, then while scaling the rope use the second grappler, repeat this till you crossed the acid lake.
MsgTutBlastedGranite=Good job! For the last hurdle you need some grappling hooks. Two per clonk, to be precise; these can be found a tunnel a little back.
MsgTutLastGrapple=Ouch! That looks like an acid lake. No chance swimming across here, the easiest way over is by alternate use of two grappling hooks. Shoot the first hook into the granite, then while scaling the rope, use the second one. Repeat this till you made your way across the acid lake.

View File

@ -78,7 +78,7 @@ void C4Team::AddPlayer(C4PlayerInfo &rInfo, bool fAdjustPlayer)
if (rInfo.IsJoined())
{
C4Player *pJoinedPlr = ::Players.GetByInfoID(rInfo.GetID());
assert(pJoinedPlr);
assert(pJoinedPlr || (rInfo.GetType() == C4PT_Script));
if (pJoinedPlr)
{
pJoinedPlr->Team = GetID();

View File

@ -609,8 +609,8 @@ bool C4Draw::BlitUnscaled(C4Surface * sfcSource, float fx, float fy, float fwdt,
int iTexX2=Min((int)(fx+fwdt-1)/iTexSizeX +1, sfcSource->iTexX);
int iTexY2=Min((int)(fy+fhgt-1)/iTexSizeY +1, sfcSource->iTexY);
// calc stretch regarding texture size and indent
float scaleX2 = scaleX * iTexSizeX;
float scaleY2 = scaleY * iTexSizeY;
/* float scaleX2 = scaleX * iTexSizeX;
float scaleY2 = scaleY * iTexSizeY;*/
// Enable textures
SetTexture();
// blit from all these textures
@ -626,12 +626,12 @@ bool C4Draw::BlitUnscaled(C4Surface * sfcSource, float fx, float fy, float fwdt,
if (iTexSizeX != pTex->iSizeX)
{
iTexSizeX = pTex->iSizeX;
scaleX2 = scaleX * iTexSizeX;
/*scaleX2 = scaleX * iTexSizeX;*/
}
if (iTexSizeY != pTex->iSizeY)
{
iTexSizeY = pTex->iSizeY;
scaleY2 = scaleY * iTexSizeY;
/*scaleY2 = scaleY * iTexSizeY;*/
}
// get new texture source bounds

View File

@ -559,8 +559,6 @@ void C4MouseControl::Draw(C4TargetFacet &cgo, const ZoomData &GameZoom)
void C4MouseControl::UpdateCursorTarget()
{
int32_t iLastCursor = Cursor;
C4Object* OldTargetObject = TargetObject;
if (Scrolling)

View File

@ -1065,17 +1065,11 @@ void C4Landscape::CompileFunc(StdCompiler *pComp)
pComp->Value(mkNamingAdapt(Modulation, "MatModulation", 0U));
pComp->Value(mkNamingAdapt(Mode, "Mode", C4LSC_Undefined));
}
static CSurface8 *GroupReadSurface8(CStdStream &hGroup)
{
// create surface
CSurface8 *pSfc=new CSurface8();
if (!pSfc->Read(hGroup))
{ delete pSfc; return NULL; }
return pSfc;
}
static CSurface8 *GroupReadSurfaceOwnPal8(CStdStream &hGroup)
static CSurface8 *GroupReadSurface8(C4Group &hGroup, const char *szWildCard)
{
if (!hGroup.AccessEntry(szWildCard))
return NULL;
// create surface
CSurface8 *pSfc=new CSurface8();
if (!pSfc->Read(hGroup))
@ -1114,18 +1108,8 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo
{
CSurface8 * sfcMap=NULL;
// Static map from scenario
if (hGroup.AccessEntry(C4CFN_Map))
if ((sfcMap=GroupReadSurface8(hGroup)))
if (!fLandscapeModeSet) Mode=C4LSC_Static;
// allow C4CFN_Landscape as map for downwards compatibility
if (!sfcMap)
if (hGroup.AccessEntry(C4CFN_Landscape))
if ((sfcMap=GroupReadSurface8(hGroup)))
{
if (!fLandscapeModeSet) Mode=C4LSC_Static;
fMapChanged = true;
}
if ((sfcMap=GroupReadSurface8(hGroup, C4CFN_Map)))
if (!fLandscapeModeSet) Mode=C4LSC_Static;
// dynamic map from file
if (!sfcMap)
@ -1198,9 +1182,6 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo
// progress
Game.SetInitProgress(80);
// mark as new-style
Game.C4S.Landscape.NewStyleLandscape = 2;
// copy noscan-var
NoScan=Game.C4S.Landscape.NoScan!=0;
@ -1209,16 +1190,19 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo
// map to big surface and sectionize it
// (not for shaders though - they require continous textures)
// Create landscape surface
Surface8 = new CSurface8();
if (!Surface8->Create(Width, Height) || !Mat2Pal())
if (!Game.C4S.Landscape.ExactLandscape)
{
delete Surface8; Surface8 = 0;
return false;
}
// Create landscape surface
Surface8 = new CSurface8();
if (!Surface8->Create(Width, Height) || !Mat2Pal())
{
delete Surface8; Surface8 = 0;
return false;
}
// Map to landscape
if (!MapToLandscape()) return false;
// Map to landscape
if (!MapToLandscape()) return false;
}
Game.SetInitProgress(84);
#ifdef DEBUGREC
@ -1394,57 +1378,24 @@ bool C4Landscape::SaveInitial()
bool C4Landscape::Load(C4Group &hGroup, bool fLoadSky, bool fSavegame)
{
// Load exact landscape from group
if (!hGroup.AccessEntry(C4CFN_Landscape)) return false;
if (!(Surface8=GroupReadSurfaceOwnPal8(hGroup))) return false;
if (!(Surface8=GroupReadSurface8(hGroup, C4CFN_Landscape))) return false;
int iWidth, iHeight;
Surface8->GetSurfaceSize(iWidth,iHeight);
Width = iWidth; Height = iHeight;
// adjust pal
if (!Mat2Pal()) return false;
// no PNG: convert old-style landscapes
if (!Game.C4S.Landscape.NewStyleLandscape)
{
// convert all pixels
for (int32_t y=0; y<Height; ++y) for (int32_t x=0; x<Width; ++x)
// Landscape should be in correct format: Make sure it is!
for (int32_t y=0; y<Height; ++y)
for (int32_t x=0; x<Width; ++x)
{
BYTE byPix = Surface8->GetPix(x, y);
int32_t iMat = PixCol2Mat(byPix);
if (byPix && !MatValid(iMat))
{
BYTE byPix = Surface8->GetPix(x, y);
int32_t iMat = PixCol2MatOld(byPix); BYTE byIFT = PixColIFTOld(byPix);
if (byIFT) byIFT = IFT;
// set pixel in 8bpp-surface only, so old-style landscapes won't be screwed up!
Surface8->SetPix(x, y, Mat2PixColDefault(iMat)+byIFT);
LogFatal(FormatString("Landscape loading error at (%d/%d): Pixel value %d not a valid material!", (int) x, (int) y, (int) byPix).getData());
return false;
}
// NewStyleLandscape-flag will be set in C4Landscape::Init later
}
// New style landscape first generation: just correct
if (Game.C4S.Landscape.NewStyleLandscape == 1)
{
// convert all pixels
for (int32_t y=0; y<Height; ++y) for (int32_t x=0; x<Width; ++x)
{
// get material
BYTE byPix = Surface8->GetPix(x, y);
int32_t iMat = PixCol2MatOld2(byPix);
if (MatValid(iMat))
// insert pixel
Surface8->SetPix(x, y, Mat2PixColDefault(iMat) + (byPix & IFT));
else
Surface8->SetPix(x, y, 0);
}
}
else
{
// Landscape should be in correct format: Make sure it is!
for (int32_t y=0; y<Height; ++y) for (int32_t x=0; x<Width; ++x)
{
BYTE byPix = Surface8->GetPix(x, y);
int32_t iMat = PixCol2Mat(byPix);
if (byPix && !MatValid(iMat))
{
LogFatal(FormatString("Landscape loading error at (%d/%d): Pixel value %d not a valid material!", (int) x, (int) y, (int) byPix).getData());
return false;
}
}
}
}
// Init sky
if (fLoadSky)
{
@ -1458,8 +1409,7 @@ bool C4Landscape::ApplyDiff(C4Group &hGroup)
{
CSurface8 *pDiff;
// Load diff landscape from group
if (!hGroup.AccessEntry(C4CFN_DiffLandscape)) return false;
if (!(pDiff=GroupReadSurfaceOwnPal8(hGroup))) return false;
if (!(pDiff=GroupReadSurface8(hGroup, C4CFN_DiffLandscape))) return false;
// convert all pixels: keep if same material; re-set if different material
BYTE byPix;
for (int32_t y=0; y<Height; ++y) for (int32_t x=0; x<Width; ++x)

View File

@ -33,10 +33,7 @@
#include <CSurface8.h>
#include <C4Material.h>
const uint8_t GBM = 128,
GBM_ColNum = 64,
IFT = 0x80,
IFTOld = GBM_ColNum;
const uint8_t IFT = 0x80;
const uint8_t CSkyDef1=104,CSkyDef2=123;
@ -319,13 +316,6 @@ inline BYTE PixColIFT(BYTE pixc)
return pixc & IFT;
}
// always use OldGfx-version (used for convert)
inline BYTE PixColIFTOld(BYTE pixc)
{
if (pixc>=GBM+IFTOld) return IFTOld;
return 0;
}
inline int32_t PixCol2Tex(BYTE pixc)
{
// Remove IFT

View File

@ -1061,26 +1061,4 @@ C4MaterialShape *C4MaterialMap::GetShapeByName(const char *name)
return &(i->second);
}
int32_t PixCol2MatOld(BYTE pixc)
{
const int C4M_ColsPerMat = 3;
if (pixc < GBM) return MNone;
pixc &= 63; // Substract GBM, ignore IFT
if (pixc > ::MaterialMap.Num*C4M_ColsPerMat-1) return MNone;
return pixc / C4M_ColsPerMat;
}
int32_t PixCol2MatOld2(BYTE pixc)
{
int32_t iMat = ((int32_t) (pixc&0x7f)) -1;
// if above MVehic, don't forget additional vehicle-colors
if (iMat<=MVehic) return iMat;
// equals middle vehicle-color
if (iMat==MVehic+1) return MVehic;
// above: range check
iMat-=2; if (iMat >= ::MaterialMap.Num) return MNone;
return iMat;
}
C4MaterialMap MaterialMap;

View File

@ -308,7 +308,4 @@ inline int32_t MatDigFree(int32_t mat)
return ::MaterialMap.Map[mat].DigFree;
}
int32_t PixCol2MatOld(BYTE pixc);
int32_t PixCol2MatOld2(BYTE pixc);
#endif

View File

@ -290,7 +290,6 @@ void C4SLandscape::Default()
NoScan=0;
KeepMapCreator=0;
SkyScrollMode=0;
NewStyleLandscape=0;
FoWRes=C4FogOfWar::DefResolutionX;
}
@ -333,7 +332,6 @@ void C4SLandscape::CompileFunc(StdCompiler *pComp)
pComp->Value(mkNamingAdapt(NoScan, "NoScan", false));
pComp->Value(mkNamingAdapt(KeepMapCreator, "KeepMapCreator", false));
pComp->Value(mkNamingAdapt(SkyScrollMode, "SkyScrollMode", 0));
pComp->Value(mkNamingAdapt(NewStyleLandscape, "NewStyleLandscape", 0));
pComp->Value(mkNamingAdapt(FoWRes, "FoWRes", static_cast<int32_t>(C4FogOfWar::DefResolutionX)));
}

View File

@ -190,7 +190,6 @@ public:
char Liquid[C4M_MaxDefName+1];
bool KeepMapCreator; // set if the mapcreator will be needed in the scenario (for DrawDefMap)
int32_t SkyScrollMode; // sky scrolling mode for newgfx
int32_t NewStyleLandscape; // if set to 2, the landscape uses up to 125 mat/texture pairs
int32_t FoWRes; // chunk size of FoGOfWar
public:
void Default();

View File

@ -1011,7 +1011,7 @@ StdMeshInstance::AttachedMesh* StdMeshInstance::AttachMesh(const StdMesh& mesh,
{
StdMeshInstance* instance = new StdMeshInstance(mesh, 1.0f);
AttachedMesh* attach = AttachMesh(*instance, denumerator, parent_bone, child_bone, transformation, flags, true);
if (!attach) { delete instance; delete denumerator; return NULL; }
if (!attach) { delete instance; return NULL; }
return attach;
}

View File

@ -917,7 +917,7 @@ void C4Network2Res::OnChunk(const C4Network2ResChunk &rChunk)
// status changed
fDirty = true;
// remove load waits
for (C4Network2ResLoad *pLoad = pLoads, *pNext, *pPrev = NULL; pLoad; pPrev = pLoad, pLoad = pNext)
for (C4Network2ResLoad *pLoad = pLoads, *pNext; pLoad; pLoad = pNext)
{
pNext = pLoad->Next();
if (static_cast<uint32_t>(pLoad->getChunk()) == rChunk.getChunkNr())

View File

@ -249,6 +249,7 @@ public:
bool isLoading() const { return fLoading; }
bool isComplete() const { return !fLoading; }
int32_t getPresentPercent() const { return fLoading ? Chunks.getPresentPercent() : 100; }
bool isTempFile() const { return fTempFile; }
bool SetByFile(const char *strFilePath, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = NULL, bool fSilent = false);
bool SetByGroup(C4Group *pGrp, bool fTemp, C4Network2ResType eType, int32_t iResID, const char *szResName = NULL, bool fSilent = false);

Some files were not shown because too many files have changed in this diff Show More