forked from Mirrors/openclonk
Merge branch 'master' into qteditor
Conflicts: planet/Objects.ocd/Items.ocd/Tools.ocd/Dynamite.ocd/Script.c planet/Objects.ocd/Libraries.ocd/Animal.ocd/CreatureControl.ocd/DefCore.txtqteditor
commit
bce903ee04
|
@ -77,6 +77,9 @@ func DrawSmallIslandsMap(proplist map)
|
||||||
if (Abs(x-w/2) < w/10) szx += Random(3); // central islands sometimes wider
|
if (Abs(x-w/2) < w/10) szx += Random(3); // central islands sometimes wider
|
||||||
map->Draw("^Ice-ice2", nil, [x-szx,y,1+2*szx,szy]);
|
map->Draw("^Ice-ice2", nil, [x-szx,y,1+2*szx,szy]);
|
||||||
}
|
}
|
||||||
|
// Balloon spawn: do nothing further
|
||||||
|
if (SCENPAR_SpawnType == 1)
|
||||||
|
return true;
|
||||||
// Starting islands for player spawns
|
// Starting islands for player spawns
|
||||||
var spawn_island_count = Max(GetStartupPlayerCount(), 2);
|
var spawn_island_count = Max(GetStartupPlayerCount(), 2);
|
||||||
g_player_spawn_positions = CreateArray(spawn_island_count);
|
g_player_spawn_positions = CreateArray(spawn_island_count);
|
||||||
|
|
|
@ -34,6 +34,24 @@ Default=1
|
||||||
Description=$DescWeaponsExplosive$
|
Description=$DescWeaponsExplosive$
|
||||||
Value=1
|
Value=1
|
||||||
|
|
||||||
|
[ParameterDef]
|
||||||
|
Name=$SpawnType$
|
||||||
|
Description=$DescSpawn$
|
||||||
|
ID=SpawnType
|
||||||
|
Default=1
|
||||||
|
|
||||||
|
[Options]
|
||||||
|
|
||||||
|
[Option]
|
||||||
|
Name=$ClassicSpawn$
|
||||||
|
Description=$DescClassicSpawn$
|
||||||
|
Value=0
|
||||||
|
|
||||||
|
[Option]
|
||||||
|
Name=$BalloonSpawn$
|
||||||
|
Description=$DescBalloonSpawn$
|
||||||
|
Value=1
|
||||||
|
|
||||||
[ParameterDef]
|
[ParameterDef]
|
||||||
Name=$Rounds$
|
Name=$Rounds$
|
||||||
Description=$DescRounds$
|
Description=$DescRounds$
|
||||||
|
|
|
@ -61,7 +61,8 @@ func InitializeRound()
|
||||||
// Checking for victory: Only active after a Clonk dies.
|
// Checking for victory: Only active after a Clonk dies.
|
||||||
g_check_victory_effect = AddEffect("CheckVictory", nil, 1, 0);
|
g_check_victory_effect = AddEffect("CheckVictory", nil, 1, 0);
|
||||||
g_player_spawn_index = 0;
|
g_player_spawn_index = 0;
|
||||||
ShuffleArray(g_player_spawn_positions);
|
if (GetType(g_player_spawn_positions) == C4V_Array)
|
||||||
|
ShuffleArray(g_player_spawn_positions);
|
||||||
|
|
||||||
// Materials: Chests
|
// Materials: Chests
|
||||||
var i,pos;
|
var i,pos;
|
||||||
|
@ -142,20 +143,34 @@ func InitPlayerRound(int plr)
|
||||||
var ls_wdt = LandscapeWidth(), ls_hgt = LandscapeHeight();
|
var ls_wdt = LandscapeWidth(), ls_hgt = LandscapeHeight();
|
||||||
var crew = GetCrew(plr), start_pos;
|
var crew = GetCrew(plr), start_pos;
|
||||||
// Position by map type?
|
// Position by map type?
|
||||||
if (g_player_spawn_positions && g_player_spawn_index < GetLength(g_player_spawn_positions))
|
if (SCENPAR_SpawnType == 0)
|
||||||
{
|
{
|
||||||
start_pos = g_player_spawn_positions[g_player_spawn_index++];
|
if (g_player_spawn_positions && g_player_spawn_index < GetLength(g_player_spawn_positions))
|
||||||
var map_zoom = ls_wdt / g_map_width;
|
{
|
||||||
start_pos = {x=start_pos[0]*map_zoom+map_zoom/2, y=start_pos[1]*map_zoom};
|
start_pos = g_player_spawn_positions[g_player_spawn_index++];
|
||||||
|
var map_zoom = ls_wdt / g_map_width;
|
||||||
|
start_pos = {x=start_pos[0]*map_zoom+map_zoom/2, y=start_pos[1]*map_zoom};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Start positions not defined or exhausted: Spawn in lower area for both maps becuase starting high is an an advantage.
|
||||||
|
start_pos = FindLocation(Loc_InRect(ls_wdt/5,ls_hgt/2,ls_wdt*3/5,ls_hgt/3), Loc_Wall(CNAT_Bottom), Loc_Func(Scenario.IsStartSpot));
|
||||||
|
if (!start_pos) start_pos = FindLocation(Loc_InRect(ls_wdt/10,0,ls_wdt*8/10,ls_hgt*4/5), Loc_Wall(CNAT_Bottom), Loc_Func(Scenario.IsStartSpot));
|
||||||
|
if (!start_pos) start_pos = {x=Random(ls_wdt*6/10)+ls_wdt*2/10, y=ls_hgt*58/100};
|
||||||
|
}
|
||||||
|
crew->SetPosition(start_pos.x, start_pos.y-10);
|
||||||
}
|
}
|
||||||
else
|
else // Balloon spawn
|
||||||
{
|
{
|
||||||
// Start positions not defined or exhausted: Spawn in lower area for both maps becuase starting high is an an advantage.
|
var spawn_x = ls_wdt/3, spawn_y = 10;
|
||||||
start_pos = FindLocation(Loc_InRect(ls_wdt/5,ls_hgt/2,ls_wdt*3/5,ls_hgt/3), Loc_Wall(CNAT_Bottom), Loc_Func(Scenario.IsStartSpot));
|
spawn_x += Random(spawn_x);
|
||||||
if (!start_pos) start_pos = FindLocation(Loc_InRect(ls_wdt/10,0,ls_wdt*8/10,ls_hgt*4/5), Loc_Wall(CNAT_Bottom), Loc_Func(Scenario.IsStartSpot));
|
var balloon = CreateObject(BalloonDeployed, spawn_x, spawn_y - 16, plr);
|
||||||
if (!start_pos) start_pos = {x=Random(ls_wdt*6/10)+ls_wdt*2/10, y=ls_hgt*58/100};
|
crew->SetPosition(spawn_x, spawn_y);
|
||||||
|
balloon->SetRider(crew);
|
||||||
|
crew->SetAction("Ride", balloon);
|
||||||
|
balloon->SetSpeed(0,0);
|
||||||
|
crew->SetSpeed(0,0);
|
||||||
}
|
}
|
||||||
crew->SetPosition(start_pos.x, start_pos.y-10);
|
|
||||||
// initial material
|
// initial material
|
||||||
if (SCENPAR_Weapons == 0)
|
if (SCENPAR_Weapons == 0)
|
||||||
{
|
{
|
||||||
|
@ -190,9 +205,19 @@ func InitPlayerRound(int plr)
|
||||||
// Disable the Clonk during the countdown.
|
// Disable the Clonk during the countdown.
|
||||||
crew->SetCrewEnabled(false);
|
crew->SetCrewEnabled(false);
|
||||||
crew->SetComDir(COMD_Stop);
|
crew->SetComDir(COMD_Stop);
|
||||||
|
|
||||||
|
if (SCENPAR_SpawnType == 1 && balloon)
|
||||||
|
balloon->CreateEffect(IntNoGravity, 1, 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local IntNoGravity = new Effect {
|
||||||
|
Timer = func() {
|
||||||
|
Target->SetSpeed(0,0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Called by the round start countdown.
|
// Called by the round start countdown.
|
||||||
func OnCountdownFinished()
|
func OnCountdownFinished()
|
||||||
{
|
{
|
||||||
|
@ -201,6 +226,8 @@ func OnCountdownFinished()
|
||||||
{
|
{
|
||||||
clonk->SetCrewEnabled(true);
|
clonk->SetCrewEnabled(true);
|
||||||
SetCursor(clonk->GetOwner(), clonk);
|
SetCursor(clonk->GetOwner(), clonk);
|
||||||
|
if (SCENPAR_SpawnType == 1 && clonk->GetActionTarget())
|
||||||
|
RemoveEffect("IntNoGravity", clonk->GetActionTarget());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,12 @@ WeaponsClassic=Klassisch
|
||||||
DescWeaponsClassic=Bögen, Speere, Keulen und einige Feuersteine
|
DescWeaponsClassic=Bögen, Speere, Keulen und einige Feuersteine
|
||||||
WeaponsExplosive=Explosiv
|
WeaponsExplosive=Explosiv
|
||||||
DescWeaponsExplosive=Nur Granatwerfer mit Endlosmunition
|
DescWeaponsExplosive=Nur Granatwerfer mit Endlosmunition
|
||||||
|
SpawnType=Startpunkte
|
||||||
|
DescSpawn=Legt fest, wo die Clonks der Spieler starten.
|
||||||
|
ClassicSpawn=Klassisch
|
||||||
|
DescClassicSpawn=Die Clonks starten auf den Eisinseln.
|
||||||
|
BalloonSpawn=Ballons
|
||||||
|
DescBalloonSpawn=Die Clonks fallen mit Ballons vom Himmel.
|
||||||
Rounds=Rundenzahl
|
Rounds=Rundenzahl
|
||||||
DescRounds=Mehrere Runden spielen
|
DescRounds=Mehrere Runden spielen
|
||||||
Stalemate=Unentschieden!
|
Stalemate=Unentschieden!
|
||||||
|
|
|
@ -5,13 +5,19 @@ DescMapTypeBigIsland=One central main island with small spots of ice in the air
|
||||||
MapTypeSpots=Small islands
|
MapTypeSpots=Small islands
|
||||||
DescMapTypeSpots=Many small spots of ice in the air.
|
DescMapTypeSpots=Many small spots of ice in the air.
|
||||||
Weapons=Weapons
|
Weapons=Weapons
|
||||||
DescWeapons=Defines which weapons are available for players
|
DescWeapons=Defines which weapons are available for players.
|
||||||
WeaponsClassic=Classic
|
WeaponsClassic=Classic
|
||||||
DescWeaponsClassic=Bows, spears and clubs available in chests
|
DescWeaponsClassic=Bows, spears and clubs available in chests.
|
||||||
WeaponsExplosive=Explosive
|
WeaponsExplosive=Explosive
|
||||||
DescWeaponsExplosive=Only grenade lauchers and wind bags available
|
DescWeaponsExplosive=Only grenade lauchers and wind bags available.
|
||||||
|
SpawnType=Spawn points
|
||||||
|
DescSpawn=Defines where the starting positions will be.
|
||||||
|
ClassicSpawn=Classic
|
||||||
|
DescClassicSpawn=All clonks start on the ice islands.
|
||||||
|
BalloonSpawn=Balloons
|
||||||
|
DescBalloonSpawn=The clonks will drop with balloons from the sky.
|
||||||
Rounds=Number of rounds
|
Rounds=Number of rounds
|
||||||
DescRounds=Play for multiple rounds
|
DescRounds=Play for multiple rounds.
|
||||||
Stalemate=Stalemate!
|
Stalemate=Stalemate!
|
||||||
WinningTeam=Winning team: %s
|
WinningTeam=Winning team: %s
|
||||||
RemainingRounds=%d rounds remaining.
|
RemainingRounds=%d rounds remaining.
|
||||||
|
|
|
@ -17,7 +17,6 @@ public func Place(int amount, proplist area)
|
||||||
var location = nil;
|
var location = nil;
|
||||||
if (area) location = Loc_InArea(area->GetBoundingRectangle());
|
if (area) location = Loc_InArea(area->GetBoundingRectangle());
|
||||||
|
|
||||||
var owner = GetCreaturePlayer();
|
|
||||||
while(amount > 0)
|
while(amount > 0)
|
||||||
{
|
{
|
||||||
var p = nil;
|
var p = nil;
|
||||||
|
@ -33,9 +32,7 @@ public func Place(int amount, proplist area)
|
||||||
// small circle
|
// small circle
|
||||||
for(var r = 0; (r < 360) && (amount > 0); r += 40+Random(40))
|
for(var r = 0; (r < 360) && (amount > 0); r += 40+Random(40))
|
||||||
{
|
{
|
||||||
var o = CreateObject(Chippie_Egg, p.x + Sin(r, 10 + RandomX(-2, 2)), p.y - Cos(r, 10 + RandomX(-2, 2)), owner);
|
var o = CreateObject(Chippie_Egg, p.x + Sin(r, 10 + RandomX(-2, 2)), p.y - Cos(r, 10 + RandomX(-2, 2)), NO_OWNER);
|
||||||
if(owner == nil)
|
|
||||||
o->SetCreatureControlled();
|
|
||||||
o->SetCon(RandomX(90, 100));
|
o->SetCon(RandomX(90, 100));
|
||||||
--amount;
|
--amount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,6 @@ public func Construction()
|
||||||
{
|
{
|
||||||
AddEffect("Activity", this, 1, 10, this);
|
AddEffect("Activity", this, 1, 10, this);
|
||||||
SetAction("Walk");
|
SetAction("Walk");
|
||||||
if (GetOwner() == NO_OWNER)
|
|
||||||
SetCreatureControlled();
|
|
||||||
energy_sucked = 0;
|
energy_sucked = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +104,7 @@ private func StartJump()
|
||||||
|
|
||||||
private func FxJumpCheckTimer(target, effect, time)
|
private func FxJumpCheckTimer(target, effect, time)
|
||||||
{
|
{
|
||||||
var e = FindObject(Find_AtPoint(), Find_OCF(OCF_Alive), Find_Hostile(GetOwner()));
|
var e = FindObject(Find_AtPoint(), Find_OCF(OCF_Alive), Find_AnimalHostile(GetOwner()));
|
||||||
if(e)
|
if(e)
|
||||||
{
|
{
|
||||||
ClawTo(e);
|
ClawTo(e);
|
||||||
|
@ -191,7 +189,7 @@ private func FxActivityTimer(target, effect, time)
|
||||||
|
|
||||||
if(!GetEffect("DmgShock", this) && !GBackSemiSolid())
|
if(!GetEffect("DmgShock", this) && !GBackSemiSolid())
|
||||||
{
|
{
|
||||||
for(var enemy in FindObjects(Find_Distance(100), Find_OCF(OCF_Alive), Find_Hostile(GetOwner()), Sort_Distance()))
|
for(var enemy in FindObjects(Find_Distance(100), Find_OCF(OCF_Alive), Find_AnimalHostile(GetOwner()), Sort_Distance()))
|
||||||
{
|
{
|
||||||
if(!PathFree(GetX(), GetY(), enemy->GetX(), enemy->GetY())) continue;
|
if(!PathFree(GetX(), GetY(), enemy->GetX(), enemy->GetY())) continue;
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,6 @@ func Construction()
|
||||||
CheckTurn(GetDir());
|
CheckTurn(GetDir());
|
||||||
|
|
||||||
SetTailOnFire();
|
SetTailOnFire();
|
||||||
|
|
||||||
SetCreatureControlled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Death()
|
func Death()
|
||||||
|
@ -508,7 +506,7 @@ func UpdateEnemy()
|
||||||
|
|
||||||
var x = GetX();
|
var x = GetX();
|
||||||
var y = GetY();
|
var y = GetY();
|
||||||
for (var obj in FindObjects(Find_Distance(200), Find_OCF(OCF_Alive), Find_Hostile(GetOwner()), Sort_Distance()))
|
for (var obj in FindObjects(Find_Distance(200), Find_OCF(OCF_Alive), Find_AnimalHostile(GetOwner()), Sort_Distance()))
|
||||||
{
|
{
|
||||||
if (!PathFree(x, y, obj->GetX(), obj->GetY())) continue;
|
if (!PathFree(x, y, obj->GetX(), obj->GetY())) continue;
|
||||||
if (obj->GBackLiquid()) continue;
|
if (obj->GBackLiquid()) continue;
|
||||||
|
|
|
@ -71,8 +71,6 @@ public func Construction()
|
||||||
if (Random(2)) SetDir(DIR_Left);
|
if (Random(2)) SetDir(DIR_Left);
|
||||||
else SetDir(DIR_Right);
|
else SetDir(DIR_Right);
|
||||||
|
|
||||||
SetCreatureControlled();
|
|
||||||
|
|
||||||
// Two spot layouts are available.
|
// Two spot layouts are available.
|
||||||
if (!Random(2))
|
if (!Random(2))
|
||||||
SetMeshMaterial("Puka2");
|
SetMeshMaterial("Puka2");
|
||||||
|
@ -348,7 +346,7 @@ private func UpdateEnemy()
|
||||||
|
|
||||||
var x = GetX();
|
var x = GetX();
|
||||||
var y = GetY();
|
var y = GetY();
|
||||||
for (var obj in FindObjects(Find_Distance(100), Find_OCF(OCF_Alive), Find_Hostile(GetOwner()), Sort_Distance()))
|
for (var obj in FindObjects(Find_Distance(100), Find_OCF(OCF_Alive), Find_AnimalHostile(GetOwner()), Sort_Distance()))
|
||||||
{
|
{
|
||||||
if (!PathFree(x, y, obj->GetX(), obj->GetY())) continue;
|
if (!PathFree(x, y, obj->GetX(), obj->GetY())) continue;
|
||||||
enemy = obj;
|
enemy = obj;
|
||||||
|
@ -377,7 +375,7 @@ private func DoElectroCircle()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Punish all close enemies (not allied animals, though).
|
// Punish all close enemies (not allied animals, though).
|
||||||
for (var obj in FindObjects(Find_Distance(30), Find_OCF(OCF_Alive), Find_Hostile(GetOwner()), Find_Exclude(this)))
|
for (var obj in FindObjects(Find_Distance(30), Find_OCF(OCF_Alive), Find_AnimalHostile(GetOwner()), Find_Exclude(this)))
|
||||||
{
|
{
|
||||||
var delta_x = 3 * (obj->GetX() - GetX());
|
var delta_x = 3 * (obj->GetX() - GetX());
|
||||||
var delta_y = 3 * (obj->GetY() - GetY());
|
var delta_y = 3 * (obj->GetY() - GetY());
|
||||||
|
@ -645,7 +643,7 @@ private func EndShockWater()
|
||||||
if (GetDir() == DIR_Right) x *= -1;
|
if (GetDir() == DIR_Right) x *= -1;
|
||||||
var y = 15;
|
var y = 15;
|
||||||
|
|
||||||
for (var obj in FindObjects(Find_Distance(120), Find_OCF(OCF_Alive), Find_Hostile(this->GetOwner())))
|
for (var obj in FindObjects(Find_Distance(120), Find_OCF(OCF_Alive), Find_AnimalHostile(this->GetOwner())))
|
||||||
{
|
{
|
||||||
if (!obj->GBackLiquid()) continue;
|
if (!obj->GBackLiquid()) continue;
|
||||||
var angle = Angle(GetX(), GetY(), obj->GetX(), obj->GetY());
|
var angle = Angle(GetX(), GetY(), obj->GetX(), obj->GetY());
|
||||||
|
|
|
@ -594,6 +594,16 @@ func CheckScaleTop()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckScaleTopHelper()
|
||||||
|
{
|
||||||
|
// Check if the clonk has passed the material with its leg vertices
|
||||||
|
// and if COMD_Up is used to climb in which case corner scale would fail
|
||||||
|
|
||||||
|
if (GBackSolid(-3+6*GetDir(), 6)) return false;
|
||||||
|
if (GetComDir() != COMD_Up) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
func FxIntScaleStart(target, effect, tmp)
|
func FxIntScaleStart(target, effect, tmp)
|
||||||
{
|
{
|
||||||
if(tmp) return;
|
if(tmp) return;
|
||||||
|
@ -624,6 +634,22 @@ func FxIntScaleTimer(target, number, time)
|
||||||
// The animation's graphics has to be shifet a bit to adjust to the clonk movement
|
// The animation's graphics has to be shifet a bit to adjust to the clonk movement
|
||||||
var pos = GetAnimationPosition(number.animation_id);
|
var pos = GetAnimationPosition(number.animation_id);
|
||||||
SetScaleRotation(0, 0, 0, 0, 0, 1);
|
SetScaleRotation(0, 0, 0, 0, 0, 1);
|
||||||
|
// Check if corner scale help is needed
|
||||||
|
if (CheckScaleTopHelper())
|
||||||
|
{
|
||||||
|
if (GetDir() == DIR_Left)
|
||||||
|
SetComDir(COMD_UpLeft);
|
||||||
|
else
|
||||||
|
SetComDir(COMD_UpRight);
|
||||||
|
number.corner_scale_helper = true;
|
||||||
|
}
|
||||||
|
else if (number.corner_scale_helper)
|
||||||
|
number.corner_scale_helper = false;
|
||||||
|
}
|
||||||
|
else if (number.corner_scale_helper)
|
||||||
|
{
|
||||||
|
// This will delay everything for 1 frame just for cleanup, hopefully it's not too bad
|
||||||
|
number.corner_scale_helper = false;
|
||||||
}
|
}
|
||||||
else if(!GBackSolid(-10+20*GetDir(), 8))
|
else if(!GBackSolid(-10+20*GetDir(), 8))
|
||||||
{
|
{
|
||||||
|
@ -708,9 +734,13 @@ func FxIntScaleStop(target, number, reason, tmp)
|
||||||
/* if(number.animation_mode == 1) PlayAnimation(Clonk_WalkStand, CLONK_ANIM_SLOT_Movement, GetWalkAnimationPosition(Clonk_WalkStand), Anim_Const(1000));
|
/* if(number.animation_mode == 1) PlayAnimation(Clonk_WalkStand, CLONK_ANIM_SLOT_Movement, GetWalkAnimationPosition(Clonk_WalkStand), Anim_Const(1000));
|
||||||
// Finally stop if the user has scheduled a stop
|
// Finally stop if the user has scheduled a stop
|
||||||
if(number.ScheduleStop) SetComDir(COMD_Stop);*/
|
if(number.ScheduleStop) SetComDir(COMD_Stop);*/
|
||||||
// and reset the transform
|
|
||||||
|
// Reset the transform
|
||||||
SetScaleRotation(0);
|
SetScaleRotation(0);
|
||||||
// SetObjDrawTransform(1000, 0, 0, 0, 1000, 0);
|
// Remove the corner scale helper com dir
|
||||||
|
if (number.corner_scale_helper)
|
||||||
|
if (GetComDir() == COMD_UpLeft || GetComDir() == COMD_UpRight)
|
||||||
|
Schedule(this, "SetComDir(COMD_Up)", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--
|
/*--
|
||||||
|
|
|
@ -108,6 +108,13 @@ protected func CatchBlow()
|
||||||
if (GetAction() == "Dead") return;
|
if (GetAction() == "Dead") return;
|
||||||
if (!Random(5)) PlaySoundHurt();
|
if (!Random(5)) PlaySoundHurt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected func OnEnergyChange(int change, int cause, int caused_by)
|
||||||
|
{
|
||||||
|
if (change < 0 && GetCursor(GetOwner()) == this)
|
||||||
|
PlayRumble(GetOwner(), Min(300 + 1000 * -change / this.MaxEnergy, 1000), 150);
|
||||||
|
return _inherited(...);
|
||||||
|
}
|
||||||
|
|
||||||
protected func Grab(object pTarget, bool fGrab)
|
protected func Grab(object pTarget, bool fGrab)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
Name=Boiling Laval
|
Name=Boiling Lava
|
||||||
Description=Causes Lava on the map to boil
|
Description=Causes Lava on the map to boil
|
||||||
|
|
|
@ -156,7 +156,7 @@ func FxIntCheckObjectsTimer(target, effect fx)
|
||||||
container_restriction = Find_Or(Find_Container(container), Find_InArray([container]));
|
container_restriction = Find_Or(Find_Container(container), Find_InArray([container]));
|
||||||
}
|
}
|
||||||
|
|
||||||
var new_objects = FindObjects(Find_AtRect(target->GetX() - 5, target->GetY() - 10, 10, 20), container_restriction, Find_Layer(target->GetObjectLayer()),
|
var new_objects = FindObjects(Find_AtRect(target->GetX() - 5, target->GetY() - 10, 10, 21), container_restriction, Find_Layer(target->GetObjectLayer()),
|
||||||
// Find all containers and objects with a custom menu.
|
// Find all containers and objects with a custom menu.
|
||||||
Find_Or(Find_Func("IsContainer"), Find_Func("HasInteractionMenu")),
|
Find_Or(Find_Func("IsContainer"), Find_Func("HasInteractionMenu")),
|
||||||
// Do not show objects with an extra slot though - even if they are containers. They count as items here and can be accessed via the surroundings tab.
|
// Do not show objects with an extra slot though - even if they are containers. They count as items here and can be accessed via the surroundings tab.
|
||||||
|
@ -997,7 +997,7 @@ func FxIntRefreshContentsMenuTimer(target, effect, time)
|
||||||
{
|
{
|
||||||
var j = 0, e = nil;
|
var j = 0, e = nil;
|
||||||
var found_tracker = false;
|
var found_tracker = false;
|
||||||
while (e = GetEffect(nil, obj, j++))
|
while (e = GetEffect("ExtraSlotTracker", obj, j++))
|
||||||
{
|
{
|
||||||
if (e.keep_alive != extra_slot_keep_alive) continue;
|
if (e.keep_alive != extra_slot_keep_alive) continue;
|
||||||
found_tracker = true;
|
found_tracker = true;
|
||||||
|
@ -1005,9 +1005,10 @@ func FxIntRefreshContentsMenuTimer(target, effect, time)
|
||||||
}
|
}
|
||||||
if (!found_tracker)
|
if (!found_tracker)
|
||||||
{
|
{
|
||||||
var e = AddEffect("ExtraSlotTracker", obj, 1, 30 + Random(60), this);
|
var e = AddEffect("ExtraSlotTracker", obj, 1, 30 + Random(60), nil, GetID());
|
||||||
e.keep_alive = extra_slot_keep_alive;
|
e.keep_alive = extra_slot_keep_alive;
|
||||||
e.callback_effect = effect;
|
e.callback_effect = effect;
|
||||||
|
e.obj = effect.obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// How many objects are this object?!
|
// How many objects are this object?!
|
||||||
|
@ -1170,8 +1171,8 @@ func FxIntRefreshContentsMenuTimer(target, effect, time)
|
||||||
|
|
||||||
func FxExtraSlotTrackerTimer(object target, proplist effect, int time)
|
func FxExtraSlotTrackerTimer(object target, proplist effect, int time)
|
||||||
{
|
{
|
||||||
if (!effect.keep_alive) return -1;
|
if (!effect.keep_alive)
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called by the extra-slot library.
|
// This is called by the extra-slot library.
|
||||||
|
|
|
@ -1,14 +1,95 @@
|
||||||
/**
|
/**
|
||||||
Dynamite
|
Dynamite
|
||||||
A volatile tool that can be pressed into wallsfor accurate
|
A volatile tool that can be pressed into wallsfor accurate mining, burning a short fuse before exploding.
|
||||||
mining, burning a short fuse before exploding.
|
|
||||||
|
@author: Newton
|
||||||
@author Newton
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*-- Engine Callbacks --*/
|
||||||
|
|
||||||
// time in frames until explosion
|
// time in frames until explosion
|
||||||
local FuseTime = 140;
|
local FuseTime = 140;
|
||||||
|
|
||||||
|
func Hit()
|
||||||
|
{
|
||||||
|
Sound("Hits::GeneralHit?");
|
||||||
|
}
|
||||||
|
|
||||||
|
func Incineration(int caused_by)
|
||||||
|
{
|
||||||
|
Extinguish();
|
||||||
|
Fuse();
|
||||||
|
SetController(caused_by);
|
||||||
|
}
|
||||||
|
|
||||||
|
func RejectEntrance()
|
||||||
|
{
|
||||||
|
return GetAction() == "Ready";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- Callbacks --*/
|
||||||
|
|
||||||
|
public func OnCannonShot(object cannon)
|
||||||
|
{
|
||||||
|
Fuse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop fusing dynamite on death to prevent explosion directly after respawn
|
||||||
|
public func IsDroppedOnDeath(object clonk)
|
||||||
|
{
|
||||||
|
return (GetAction() == "Fuse");
|
||||||
|
}
|
||||||
|
|
||||||
|
public func IsFusing()
|
||||||
|
{
|
||||||
|
return GetAction() == "Fuse";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by the Dynamite box
|
||||||
|
public func SetReady()
|
||||||
|
{
|
||||||
|
SetAction("Ready");
|
||||||
|
}
|
||||||
|
// Called by the Dynamite box
|
||||||
|
public func SetFuse()
|
||||||
|
{
|
||||||
|
SetAction("Fuse");
|
||||||
|
// Object can't be collected anymore when it fuses.
|
||||||
|
this.Collectible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func Reset()
|
||||||
|
{
|
||||||
|
SetAction("Idle");
|
||||||
|
// Object can be collected again.
|
||||||
|
this.Collectible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func OnFuseFinished(object fuse)
|
||||||
|
{
|
||||||
|
SetController(fuse->GetController());
|
||||||
|
DoExplode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will only when inside a dynamite box to display the remaining dynamite sticks in the HUD
|
||||||
|
public func GetStackCount()
|
||||||
|
{
|
||||||
|
if (Contained())
|
||||||
|
if (Contained()->GetID() == DynamiteBox)
|
||||||
|
{
|
||||||
|
return Contained()->ContentsCount(GetID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func IsInfiniteStackCount()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func IsGrenadeLauncherAmmo() { return true; }
|
||||||
|
|
||||||
|
/*-- Usage --*/
|
||||||
|
|
||||||
public func ControlUse(object clonk, int x, int y, bool box)
|
public func ControlUse(object clonk, int x, int y, bool box)
|
||||||
{
|
{
|
||||||
// if already activated, nothing (so, throw)
|
// if already activated, nothing (so, throw)
|
||||||
|
@ -52,7 +133,19 @@ public func ControlUse(object clonk, int x, int y, bool box)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private func Place(object clonk, int x, int y, bool box)
|
public func Fuse()
|
||||||
|
{
|
||||||
|
if (GetAction() != "Fuse")
|
||||||
|
{
|
||||||
|
if (!FindObject(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
|
||||||
|
Sound("Fire::Fuse");
|
||||||
|
SetAction("Fuse");
|
||||||
|
// Object can't be collected anymore when it fuses.
|
||||||
|
this.Collectible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Place(object clonk, int x, int y, bool box)
|
||||||
{
|
{
|
||||||
var angle = Angle(0,0,x,y);
|
var angle = Angle(0,0,x,y);
|
||||||
var pos = GetWall(angle);
|
var pos = GetWall(angle);
|
||||||
|
@ -69,26 +162,9 @@ private func Place(object clonk, int x, int y, bool box)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func Fuse()
|
|
||||||
{
|
|
||||||
if (GetAction() != "Fuse")
|
|
||||||
{
|
|
||||||
if (!FindObject(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this)))
|
|
||||||
Sound("Fire::Fuse");
|
|
||||||
SetAction("Fuse");
|
|
||||||
// Object can't be collected anymore when it fuses.
|
|
||||||
this.Collectible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func OnCannonShot(object cannon)
|
|
||||||
{
|
|
||||||
Fuse();
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns true if there is a wall in direction in which "clonk" looks
|
// returns true if there is a wall in direction in which "clonk" looks
|
||||||
// and puts the offset to the wall into "xo, yo" - looking from the clonk
|
// and puts the offset to the wall into "xo, yo" - looking from the clonk
|
||||||
private func GetWall(int angle)
|
func GetWall(int angle)
|
||||||
{
|
{
|
||||||
var dist = 12;
|
var dist = 12;
|
||||||
for (var dist = 12; dist < 18; dist++)
|
for (var dist = 12; dist < 18; dist++)
|
||||||
|
@ -101,41 +177,7 @@ private func GetWall(int angle)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected func Hit() { Sound("Hits::GeneralHit?"); }
|
func Fusing()
|
||||||
|
|
||||||
protected func Incineration(int caused_by)
|
|
||||||
{
|
|
||||||
Extinguish();
|
|
||||||
Fuse();
|
|
||||||
SetController(caused_by);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected func RejectEntrance()
|
|
||||||
{
|
|
||||||
return GetAction() == "Ready";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Controle of the Dynamite box
|
|
||||||
public func SetReady()
|
|
||||||
{
|
|
||||||
SetAction("Ready");
|
|
||||||
}
|
|
||||||
// Controle of the Dynamite box
|
|
||||||
public func SetFuse()
|
|
||||||
{
|
|
||||||
SetAction("Fuse");
|
|
||||||
// Object can't be collected anymore when it fuses.
|
|
||||||
this.Collectible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public func Reset()
|
|
||||||
{
|
|
||||||
SetAction("Idle");
|
|
||||||
// Object can be collected again.
|
|
||||||
this.Collectible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private func Fusing()
|
|
||||||
{
|
{
|
||||||
var x = Sin(GetR(), 5);
|
var x = Sin(GetR(), 5);
|
||||||
var y = -Cos(GetR(), 5);
|
var y = -Cos(GetR(), 5);
|
||||||
|
@ -155,11 +197,6 @@ private func Fusing()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func OnFuseFinished(object fuse)
|
|
||||||
{
|
|
||||||
SetController(fuse->GetController());
|
|
||||||
DoExplode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public func DoExplode()
|
public func DoExplode()
|
||||||
{
|
{
|
||||||
|
@ -169,17 +206,9 @@ public func DoExplode()
|
||||||
Explode(26);
|
Explode(26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-- Production --*/
|
||||||
|
|
||||||
public func IsChemicalProduct() { return true; }
|
public func IsChemicalProduct() { return true; }
|
||||||
public func IsGrenadeLauncherAmmo() { return true; }
|
|
||||||
|
|
||||||
public func IsFusing() { return GetAction() == "Fuse"; }
|
|
||||||
|
|
||||||
// Drop fusing dynamite on death to prevent explosion directly after respawn
|
|
||||||
public func IsDroppedOnDeath(object clonk)
|
|
||||||
{
|
|
||||||
return (GetAction() == "Fuse");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-- Properties --*/
|
/*-- Properties --*/
|
||||||
|
|
||||||
|
@ -207,8 +236,7 @@ local ActMap = {
|
||||||
};
|
};
|
||||||
local Name = "$Name$";
|
local Name = "$Name$";
|
||||||
local Description = "$Description$";
|
local Description = "$Description$";
|
||||||
local Collectible = 1;
|
local Collectible = true;
|
||||||
|
|
||||||
local BlastIncinerate = 1;
|
local BlastIncinerate = 1;
|
||||||
local ContactIncinerate = 1;
|
local ContactIncinerate = 1;
|
||||||
local Components = {Coal = 1, Firestone = 1};
|
local Components = {Coal = 1, Firestone = 1};
|
|
@ -38,9 +38,11 @@ public func ControlUse(object clonk, int x, int y)
|
||||||
{
|
{
|
||||||
if (clonk->GetAction() != "Walk")
|
if (clonk->GetAction() != "Walk")
|
||||||
return true;
|
return true;
|
||||||
|
if (ignited)
|
||||||
ignited = 1;
|
return true;
|
||||||
|
|
||||||
|
ignited = true;
|
||||||
|
|
||||||
// The clonk has to stand.
|
// The clonk has to stand.
|
||||||
clonk->SetAction("Stand");
|
clonk->SetAction("Stand");
|
||||||
clonk->SetXDir(0);
|
clonk->SetXDir(0);
|
||||||
|
@ -91,7 +93,13 @@ public func GetCarryMode()
|
||||||
|
|
||||||
public func GetCarryPhase() { return 250; }
|
public func GetCarryPhase() { return 250; }
|
||||||
|
|
||||||
public func GetCarrySpecial(clonk)
|
public func GetCarryTransform()
|
||||||
|
{
|
||||||
|
if (ignited)
|
||||||
|
return Trans_Mul(Trans_Rotate(0, 1), Trans_Translate(-1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
public func GetCarrySpecial()
|
||||||
{
|
{
|
||||||
if (ignited)
|
if (ignited)
|
||||||
return "pos_hand2";
|
return "pos_hand2";
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
/**
|
/**
|
||||||
Dynamite box
|
Dynamite box
|
||||||
Contains five dynamite sticks which can be placed and detonated from a distance.
|
Contains five dynamite sticks which can be placed and detonated from a distance.
|
||||||
|
|
||||||
@author: Newton
|
@author: Newton
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include Library_HasExtraSlot
|
||||||
|
|
||||||
static const DYNA_MaxLength = 500;
|
static const DYNA_MaxLength = 500;
|
||||||
static const DYNA_MaxCount = 5;
|
static const DYNA_MaxCount = 5;
|
||||||
|
|
||||||
|
@ -17,6 +19,8 @@ local wire;
|
||||||
|
|
||||||
func Initialize()
|
func Initialize()
|
||||||
{
|
{
|
||||||
|
CreateContents(Dynamite, DYNA_MaxCount);
|
||||||
|
|
||||||
count = DYNA_MaxCount;
|
count = DYNA_MaxCount;
|
||||||
dynamite_sticks = [];
|
dynamite_sticks = [];
|
||||||
wires = [];
|
wires = [];
|
||||||
|
@ -29,7 +33,6 @@ func Initialize()
|
||||||
// Hide it TODO: Remove if the mesh isn't shown if there is a picture set
|
// Hide it TODO: Remove if the mesh isn't shown if there is a picture set
|
||||||
this.PictureTransformation = Trans_Scale();
|
this.PictureTransformation = Trans_Scale();
|
||||||
UpdatePicture();
|
UpdatePicture();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Hit()
|
func Hit()
|
||||||
|
@ -37,24 +40,84 @@ func Hit()
|
||||||
Sound("Hits::Materials::Wood::DullWoodHit?");
|
Sound("Hits::Materials::Wood::DullWoodHit?");
|
||||||
}
|
}
|
||||||
|
|
||||||
func Incineration(int caused_by)
|
func Incineration(int caused_by)
|
||||||
{
|
{
|
||||||
ActivateFuse();
|
ActivateFuse();
|
||||||
if (!GetEffect("Fuse", this)) AddEffect("Fuse", this, 100, 1, this);
|
if (!GetEffect("Fuse", this)) AddEffect("Fuse", this, 100, 1, this);
|
||||||
Sound("Fire::Fuse");
|
Sound("Fire::Fuse");
|
||||||
SetController(caused_by);
|
SetController(caused_by);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Damage(int change, int type, int by_player)
|
func Damage(int change, int type, int by_player)
|
||||||
{
|
{
|
||||||
Incinerate(nil, by_player);
|
Incinerate(nil, by_player);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func OnCannonShot(object cannon)
|
func RejectCollect(id def, object obj)
|
||||||
{
|
{
|
||||||
Incinerate(nil, cannon->GetController());
|
if (obj->GetID() != Dynamite)
|
||||||
|
return true;
|
||||||
|
// One dynamite box can only support 5 sticks of dynamite, regardless if these are in the box
|
||||||
|
// or already taken out (connected with wires)
|
||||||
|
var sticks = ContentsCount(Dynamite);
|
||||||
|
for (var i = 0; i < GetLength(wires); i++)
|
||||||
|
if (wires[i])
|
||||||
|
sticks++;
|
||||||
|
|
||||||
|
if (sticks >= DYNA_MaxCount)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ejection()
|
||||||
|
{
|
||||||
|
count--;
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
ChangeToIgniter();
|
||||||
|
if (Contained())
|
||||||
|
{
|
||||||
|
var pos = Contained()->~GetItemPos(this);
|
||||||
|
Contained()->~UpdateAttach();
|
||||||
|
Contained()->~OnSlotFull(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdatePicture();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the inventory gets notified of the changes.
|
||||||
|
if (Contained())
|
||||||
|
Contained()->~OnInventoryChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContentsDestruction()
|
||||||
|
{
|
||||||
|
Ejection();
|
||||||
|
}
|
||||||
|
|
||||||
|
func Collection2()
|
||||||
|
{
|
||||||
|
if (count == 0 && GetID() == Igniter)
|
||||||
|
{
|
||||||
|
ChangeToBox();
|
||||||
|
if (Contained())
|
||||||
|
{
|
||||||
|
var pos = Contained()->~GetItemPos(this);
|
||||||
|
Contained()->~UpdateAttach();
|
||||||
|
Contained()->~OnSlotFull(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
|
||||||
|
UpdatePicture();
|
||||||
|
|
||||||
|
if (Contained())
|
||||||
|
Contained()->~OnInventoryChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-- Callbacks --*/
|
/*-- Callbacks --*/
|
||||||
|
@ -78,6 +141,11 @@ public func OnFuseFinished(object fuse)
|
||||||
DoExplode();
|
DoExplode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func OnCannonShot(object cannon)
|
||||||
|
{
|
||||||
|
Incinerate(nil, cannon->GetController());
|
||||||
|
}
|
||||||
|
|
||||||
/*-- Usage --*/
|
/*-- Usage --*/
|
||||||
|
|
||||||
public func SetDynamiteCount(int new_count)
|
public func SetDynamiteCount(int new_count)
|
||||||
|
@ -87,49 +155,34 @@ public func SetDynamiteCount(int new_count)
|
||||||
// Update inventory if contained in a crew member.
|
// Update inventory if contained in a crew member.
|
||||||
if (Contained())
|
if (Contained())
|
||||||
Contained()->~OnInventoryChange();
|
Contained()->~OnInventoryChange();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func HoldingEnabled() { return true; }
|
|
||||||
|
|
||||||
public func ControlUse(object clonk, int x, int y)
|
public func ControlUse(object clonk, int x, int y)
|
||||||
{
|
{
|
||||||
var dynamite = dynamite_sticks[count - 1] = CreateContents(Dynamite);
|
var dynamite = Contents();
|
||||||
|
|
||||||
|
if (!dynamite || dynamite->GetID() != Dynamite)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!dynamite->ControlUse(clonk, x, y, 1))
|
if (!dynamite->ControlUse(clonk, x, y, 1))
|
||||||
{
|
|
||||||
dynamite->RemoveObject();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
if(wire)
|
if(wire)
|
||||||
wire->Connect(dynamite_sticks[count], dynamite);
|
wire->Connect(dynamite_sticks[count], dynamite);
|
||||||
|
|
||||||
wire = CreateObject(Fuse);
|
wire = CreateObject(Fuse);
|
||||||
wire->Connect(dynamite, this);
|
wire->Connect(dynamite, this);
|
||||||
Sound("Objects::Connect");
|
Sound("Objects::Connect");
|
||||||
wires[count - 1] = wire;
|
wires[count] = wire;
|
||||||
|
|
||||||
count--;
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
var pos = clonk->GetItemPos(this);
|
|
||||||
ChangeToIgniter();
|
|
||||||
clonk->UpdateAttach();
|
|
||||||
clonk->OnSlotFull(pos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdatePicture();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the inventory gets notified of the changes.
|
|
||||||
clonk->~OnInventoryChange();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty this box and turn it into an igniter
|
// Empty this box and turn it into an igniter
|
||||||
public func ChangeToIgniter()
|
public func ChangeToIgniter()
|
||||||
{
|
{
|
||||||
|
if (GetID() == Igniter) return;
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
UpdatePicture();
|
UpdatePicture();
|
||||||
ChangeDef(Igniter);
|
ChangeDef(Igniter);
|
||||||
|
@ -137,6 +190,16 @@ public func ChangeToIgniter()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change back into a box
|
||||||
|
public func ChangeToBox()
|
||||||
|
{
|
||||||
|
if (GetID() == DynamiteBox) return;
|
||||||
|
|
||||||
|
ChangeDef(DynamiteBox);
|
||||||
|
UpdatePicture();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public func ActivateFuse()
|
public func ActivateFuse()
|
||||||
{
|
{
|
||||||
// Activate all fuses.
|
// Activate all fuses.
|
||||||
|
@ -199,7 +262,7 @@ func UpdatePicture()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the remaining dynamite sticks in menus.
|
// Display the remaining dynamite sticks in menus.
|
||||||
public func GetInventoryIconOverlay()
|
/*public func GetInventoryIconOverlay()
|
||||||
{
|
{
|
||||||
// Full boxes don't need an overlay. Same for igniters.
|
// Full boxes don't need an overlay. Same for igniters.
|
||||||
if (count == DYNA_MaxCount || count <= 0) return nil;
|
if (count == DYNA_MaxCount || count <= 0) return nil;
|
||||||
|
@ -231,17 +294,19 @@ public func GetInventoryIconOverlay()
|
||||||
}
|
}
|
||||||
|
|
||||||
return overlay;
|
return overlay;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
func Definition(def) {
|
func Definition(def)
|
||||||
|
{
|
||||||
SetProperty("PictureTransformation", Trans_Mul(Trans_Rotate(150, 1, 0, 0), Trans_Rotate(140, 0, 1, 0)), def);
|
SetProperty("PictureTransformation", Trans_Mul(Trans_Rotate(150, 1, 0, 0), Trans_Rotate(140, 0, 1, 0)), def);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-- Properties --*/
|
/*-- Properties --*/
|
||||||
|
|
||||||
local Collectible = 1;
|
|
||||||
local Name = "$Name$";
|
local Name = "$Name$";
|
||||||
local Description = "$Description$";
|
local Description = "$Description$";
|
||||||
|
local Collectible = true;
|
||||||
local BlastIncinerate = 1;
|
local BlastIncinerate = 1;
|
||||||
local ContactIncinerate = 2;
|
local ContactIncinerate = 2;
|
||||||
local Components = {Wood = 1, Coal = 2, Firestone = 2};
|
local Components = {Wood = 1, Coal = 2, Firestone = 2};
|
||||||
|
local MaxContentsCount = 5;
|
|
@ -169,8 +169,10 @@ public func OnRopeBreak()
|
||||||
|
|
||||||
/*-- Grapple rope controls --*/
|
/*-- Grapple rope controls --*/
|
||||||
|
|
||||||
public func FxIntGrappleControlControl(object target, proplist effect, int ctrl, int x, int y, int strength, repeat, release)
|
public func FxIntGrappleControlControl(object target, proplist effect, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
|
if (status == CONS_Moved) return false;
|
||||||
|
var release = status == CONS_Up;
|
||||||
// Cancel this effect if clonk is now attached to something.
|
// Cancel this effect if clonk is now attached to something.
|
||||||
if (target->GetProcedure() == "ATTACH")
|
if (target->GetProcedure() == "ATTACH")
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,11 +101,14 @@ public func CanBeStackedWith(object other)
|
||||||
return inherited(other) && (PipeState == other.PipeState);
|
return inherited(other) && (PipeState == other.PipeState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The pump calls this function to prevent clogging of the intake.
|
The pump calls this function to prevent clogging of the intake.
|
||||||
Cycles through several aperture offset indices.
|
Cycles through several aperture offset indices.
|
||||||
*/
|
*/
|
||||||
func CycleApertureOffset()
|
public func HasAperture() { return true; }
|
||||||
|
|
||||||
|
public func CycleApertureOffset()
|
||||||
{
|
{
|
||||||
// Cycle in three steps of three px each through X and Y
|
// Cycle in three steps of three px each through X and Y
|
||||||
// covering a 3x3 grid on points -3,0,+3
|
// covering a 3x3 grid on points -3,0,+3
|
||||||
|
|
|
@ -33,6 +33,8 @@ public func IsDigging() { return is_digging; }
|
||||||
|
|
||||||
public func HoldingEnabled() { return true; }
|
public func HoldingEnabled() { return true; }
|
||||||
|
|
||||||
|
public func DefaultCrosshairAngle(object clonk, int d) { return 900 * d; }
|
||||||
|
|
||||||
public func ControlUseStart(object clonk, int x, int y)
|
public func ControlUseStart(object clonk, int x, int y)
|
||||||
{
|
{
|
||||||
AddEffect("ShovelDig", clonk, 1, 1, this);
|
AddEffect("ShovelDig", clonk, 1, 1, this);
|
||||||
|
|
|
@ -22,7 +22,15 @@ func Hit()
|
||||||
|
|
||||||
/*-- Usage --*/
|
/*-- Usage --*/
|
||||||
|
|
||||||
public func ControlUse(object clonk, x, y)
|
public func DefaultCrosshairAngle(object clonk, int d)
|
||||||
|
{
|
||||||
|
// Easy mode for gamepad users: automatically boost a jump.
|
||||||
|
if (clonk->GetYDir() < -10)
|
||||||
|
return Angle(0, 0, -clonk->GetXDir(), -clonk->GetYDir(), 10);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected func ControlUse(object clonk, x, y)
|
||||||
{
|
{
|
||||||
if (!GetEffect("IntReload", this) && !GetEffect("IntBurstWind", this))
|
if (!GetEffect("IntReload", this) && !GetEffect("IntBurstWind", this))
|
||||||
{
|
{
|
||||||
|
@ -251,4 +259,4 @@ local Name = "$Name$";
|
||||||
local Description = "$Description$";
|
local Description = "$Description$";
|
||||||
local Collectible = true;
|
local Collectible = true;
|
||||||
local MaxIntake = 30;
|
local MaxIntake = 30;
|
||||||
local Components = {Cloth = 1, Metal = 1};
|
local Components = {Cloth = 1, Metal = 1};
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
[DefCore]
|
||||||
|
id=Helmet
|
||||||
|
Version=8,0
|
||||||
|
Category=C4D_Object
|
||||||
|
Width=10
|
||||||
|
Height=10
|
||||||
|
Offset=-5,-5
|
||||||
|
Vertices=2
|
||||||
|
VertexX=0,0
|
||||||
|
VertexY=-4,5
|
||||||
|
VertexFriction=50,50
|
||||||
|
Value=10
|
||||||
|
Mass=10
|
||||||
|
Rotate=1
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,23 @@
|
||||||
|
material Helmet_Greek
|
||||||
|
{
|
||||||
|
receive_shadows on
|
||||||
|
technique
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
cull_hardware none
|
||||||
|
|
||||||
|
ambient 0.8 0.8 0.8 1.0
|
||||||
|
diffuse 0.64 0.64 0.64 1.0
|
||||||
|
specular 0.16 0.16 0.16 1.0 12.5
|
||||||
|
emissive 0.0 0.0 0.0 1.0
|
||||||
|
|
||||||
|
texture_unit
|
||||||
|
{
|
||||||
|
texture helmet.jpg
|
||||||
|
tex_address_mode wrap
|
||||||
|
filtering trilinear
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/**
|
||||||
|
Helmet
|
||||||
|
Protective head armor.
|
||||||
|
|
||||||
|
@author: pluto, Clonkonaut
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include Library_Wearable
|
||||||
|
|
||||||
|
/*-- Engine Callbacks --*/
|
||||||
|
|
||||||
|
func Hit()
|
||||||
|
{
|
||||||
|
Sound("Hits::Materials::Metal::DullMetalHit?");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- Usage --*/
|
||||||
|
|
||||||
|
public func ControlUse(object clonk)
|
||||||
|
{
|
||||||
|
if (IsWorn())
|
||||||
|
TakeOff();
|
||||||
|
else
|
||||||
|
PutOn(clonk);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helmet effect: 20% less damage
|
||||||
|
func OnDamage(int damage, int cause, int by_player)
|
||||||
|
{
|
||||||
|
// Do nothing on energy gained
|
||||||
|
if (damage > 0) return damage;
|
||||||
|
// Doesn't protect against all damage
|
||||||
|
if (cause == FX_Call_EngBlast || cause == FX_Call_EngFire || cause == FX_Call_EngAsphyxiation || cause == FX_Call_EngCorrosion)
|
||||||
|
return damage;
|
||||||
|
|
||||||
|
return damage - (damage*20/100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- Production --*/
|
||||||
|
|
||||||
|
public func IsWeapon() { return true; }
|
||||||
|
public func IsArmoryProduct() { return true; }
|
||||||
|
|
||||||
|
/*-- Display --*/
|
||||||
|
|
||||||
|
public func GetWearPlace()
|
||||||
|
{
|
||||||
|
return WEARABLE_Head;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func GetWearBone()
|
||||||
|
{
|
||||||
|
return "Main";
|
||||||
|
}
|
||||||
|
|
||||||
|
public func GetWearTransform()
|
||||||
|
{
|
||||||
|
return Trans_Mul(Trans_Rotate(90, 0, 0, 1), Trans_Translate(0, -300));
|
||||||
|
}
|
||||||
|
|
||||||
|
public func GetCarryMode(object clonk, bool secondary)
|
||||||
|
{
|
||||||
|
if (IsWorn() || display_disabled)
|
||||||
|
return CARRY_None;
|
||||||
|
if (secondary || !clonk->~HasHandAction(false, true))
|
||||||
|
return CARRY_Back;
|
||||||
|
return CARRY_BothHands;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func GetCarryPhase(object clonk)
|
||||||
|
{
|
||||||
|
return 550;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func GetCarryBone(object clonk, bool secondary)
|
||||||
|
{
|
||||||
|
return "Main";
|
||||||
|
}
|
||||||
|
|
||||||
|
public func GetCarryTransform(object clonk, bool secondary, bool no_hand, bool on_back)
|
||||||
|
{
|
||||||
|
if (secondary)
|
||||||
|
return Trans_Mul(Trans_Rotate(180, 1), Trans_Rotate(0, 0, 1), Trans_Rotate(90, 0, 0, 1), Trans_Translate(-4000));
|
||||||
|
if (no_hand || on_back)
|
||||||
|
return Trans_Mul(Trans_Rotate(0, 1), Trans_Rotate(0, 0, 1), Trans_Rotate(90, 0, 0, 1), Trans_Translate(-4000));
|
||||||
|
|
||||||
|
return Trans_Mul(Trans_Rotate(80, 0, 0, 1), Trans_Rotate(-90, 0, 1), Trans_Rotate(-45, 0, 0, 1), Trans_Translate(-1000, 4000));
|
||||||
|
}
|
||||||
|
|
||||||
|
func Definition(def)
|
||||||
|
{
|
||||||
|
SetProperty("PictureTransformation", Trans_Mul(Trans_Rotate(45, 0, 1), Trans_Rotate(10, 0, 0, 1)),def);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- Properties --*/
|
||||||
|
|
||||||
|
local Name = "$Name$";
|
||||||
|
local Description = "$Description$";
|
||||||
|
local Collectible = true;
|
||||||
|
local Components = {Wood = 1, Metal = 1};
|
|
@ -0,0 +1,2 @@
|
||||||
|
Name=Helm
|
||||||
|
Description=Bietet dem Clonk einigen Schutz. Drücke [Benutzen] um den Helm auf- oder abzusetzen.
|
|
@ -0,0 +1,2 @@
|
||||||
|
Name=Helmet
|
||||||
|
Description=Provides the clonk with some protection. Press [Use] to take the helmet on or off.
|
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
|
@ -1,5 +0,0 @@
|
||||||
[DefCore]
|
|
||||||
id=Library_CreatureControl
|
|
||||||
Version=6,1
|
|
||||||
Category=C4D_StaticBack
|
|
||||||
HideInCreator=true
|
|
|
@ -1,76 +0,0 @@
|
||||||
/**
|
|
||||||
AnimalControl
|
|
||||||
Cares about the ownership of non-player-controlled units.
|
|
||||||
They are hostile to every other player.
|
|
||||||
|
|
||||||
global func GetCreaturePlayer()
|
|
||||||
global func SetAnimalControlled()
|
|
||||||
*/
|
|
||||||
|
|
||||||
static CreatureControl_animal_player;
|
|
||||||
static CreatureControl_yet_to_set;
|
|
||||||
static CreatureControl_initializing;
|
|
||||||
|
|
||||||
private func Enqueue(obj)
|
|
||||||
{
|
|
||||||
if(GetType(CreatureControl_yet_to_set) != C4V_Array)
|
|
||||||
CreatureControl_yet_to_set = [];
|
|
||||||
PushBack(CreatureControl_yet_to_set, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the hostile NPC player or creates it.
|
|
||||||
Returns nil when the NPC player is currently joining.
|
|
||||||
*/
|
|
||||||
global func GetCreaturePlayer()
|
|
||||||
{
|
|
||||||
if(CreatureControl_animal_player != nil)
|
|
||||||
return CreatureControl_animal_player;
|
|
||||||
if(CreatureControl_initializing == true)
|
|
||||||
return nil;
|
|
||||||
|
|
||||||
CreatureControl_initializing = true;
|
|
||||||
CreateScriptPlayer("Creatures", RGB(50, 100, 50), 0, CSPF_NoScenarioInit | CSPF_NoEliminationCheck | CSPF_Invisible, Library_CreatureControl);
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Sets the owner of an object to the hostile NPC player.
|
|
||||||
*/
|
|
||||||
global func SetCreatureControlled()
|
|
||||||
{
|
|
||||||
if(!this) return false;
|
|
||||||
var o = GetCreaturePlayer();
|
|
||||||
if(o != nil) return SetOwner(o);
|
|
||||||
|
|
||||||
// No owner during creation. If the scripter overwrites it to a real owner, it's not changed later.
|
|
||||||
SetOwner(NO_OWNER);
|
|
||||||
Library_CreatureControl->Enqueue(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public func InitializeScriptPlayer(plr, team)
|
|
||||||
{
|
|
||||||
CreatureControl_animal_player = plr;
|
|
||||||
|
|
||||||
if(CreatureControl_yet_to_set != nil)
|
|
||||||
{
|
|
||||||
for(var obj in CreatureControl_yet_to_set)
|
|
||||||
{
|
|
||||||
if (!obj) continue;
|
|
||||||
|
|
||||||
// Overwritten by the scripter?
|
|
||||||
if (obj->GetOwner() != NO_OWNER) continue;
|
|
||||||
obj->SetOwner(CreatureControl_animal_player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CreatureControl_yet_to_set = nil;
|
|
||||||
|
|
||||||
// hostile!
|
|
||||||
for(var i = 0; i < GetPlayerCount(); ++i)
|
|
||||||
{
|
|
||||||
var p = GetPlayerByIndex(i);
|
|
||||||
if(p == CreatureControl_animal_player) continue;
|
|
||||||
SetHostility(p, plr, true, true, true);
|
|
||||||
SetHostility(plr, p, true, true, true);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,68 +5,85 @@
|
||||||
Virtual cursor for gamepad controls
|
Virtual cursor for gamepad controls
|
||||||
*/
|
*/
|
||||||
|
|
||||||
local crew, angle, dirx, diry, xpos,ypos, analogaim, aiming, menu;
|
local crew, angle, xpos, ypos, aiming, menu;
|
||||||
|
|
||||||
static const CURSOR_Radius = 100;
|
static const CURSOR_Radius = 100;
|
||||||
|
// This is supposed to be a constant, but C4Script doesn't allow constant expressions there.
|
||||||
|
private func CURSOR_Deadzone() { return PLRCON_MaxStrength / 5; }
|
||||||
|
|
||||||
protected func Initialize()
|
protected func Initialize()
|
||||||
{
|
{
|
||||||
this["Visibility"] = VIS_None;
|
SetVisibility(false);
|
||||||
dirx = diry = xpos = ypos = 0;
|
xpos = ypos = 0;
|
||||||
aiming = false;
|
aiming = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func FxMoveTimer()
|
public func FxMoveTimer()
|
||||||
{
|
{
|
||||||
var speed = 0;
|
if (!crew)
|
||||||
var dpad_rotatespeed = 35;
|
|
||||||
|
|
||||||
// dpad mode
|
|
||||||
if(diry)
|
|
||||||
{
|
{
|
||||||
if (diry < 0) speed = -Sin(angle,100,10);
|
RemoveObject();
|
||||||
else if (diry > 0) speed = +Sin(angle,100,10);
|
return FX_Execute_Kill;
|
||||||
angle += dpad_rotatespeed*speed/100;
|
|
||||||
UpdateAnalogpadPos();
|
|
||||||
}
|
}
|
||||||
if(dirx)
|
|
||||||
{
|
|
||||||
if (dirx < 0) speed = -Cos(angle,100,10);
|
|
||||||
else if (dirx > 0) speed = +Cos(angle,100,10);
|
|
||||||
angle += dpad_rotatespeed*speed/100;
|
|
||||||
UpdateAnalogpadPos();
|
|
||||||
}
|
|
||||||
// analog pad mode
|
|
||||||
if(!dirx && !diry)
|
|
||||||
{
|
|
||||||
var target_angle = Angle(0,0,xpos,ypos)*10;
|
|
||||||
var analog_strength = BoundBy(Sqrt(xpos*xpos+ypos*ypos),0,100);
|
|
||||||
|
|
||||||
|
var target_angle = Angle(0,0,xpos,ypos)*10;
|
||||||
|
|
||||||
|
if (!Visible() && !InDeadzone())
|
||||||
|
{
|
||||||
|
// The player moved the aiming stick while the crosshair wasn't visible: Use angle directly.
|
||||||
|
angle = target_angle;
|
||||||
|
SetVisibility(true);
|
||||||
|
}
|
||||||
|
else if (!InDeadzone())
|
||||||
|
{
|
||||||
|
// Smooth small movements of the stick while the crosshair is visible.
|
||||||
var angle_diff = Normalize(target_angle - angle, -1800, 10);
|
var angle_diff = Normalize(target_angle - angle, -1800, 10);
|
||||||
if (angle_diff == 0) angle_diff = 1;
|
if (Abs(angle_diff) < 450)
|
||||||
|
angle = angle + angle_diff / 8;
|
||||||
angle = angle + angle_diff * analog_strength / 100 / 8;
|
else
|
||||||
|
angle = target_angle;
|
||||||
|
}
|
||||||
|
else if (!aiming)
|
||||||
|
{
|
||||||
|
// The player doesn't touch the stick and no item is using the crosshair right now.
|
||||||
|
SetVisibility(false);
|
||||||
|
// Aim somewhere useful. Note that this can be overwritten by objects and isn't used for throwing.
|
||||||
|
angle = 800*(crew->GetDir()*2-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
if(aiming) crew->TriggerHoldingControl();
|
crew->TriggerHoldingControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
private func UpdateAnalogpadPos()
|
private func AnalogStrength() { return BoundBy(Sqrt(xpos*xpos+ypos*ypos), 0, PLRCON_MaxStrength); }
|
||||||
|
private func InDeadzone() { return AnalogStrength() < CURSOR_Deadzone(); }
|
||||||
|
private func Visible() { return this.Visibility != VIS_None; }
|
||||||
|
|
||||||
|
// Updates the visibility, returing true if it was changed.
|
||||||
|
private func SetVisibility(bool visible)
|
||||||
{
|
{
|
||||||
xpos = Sin(angle/10,100);
|
var newvis, oldvis;
|
||||||
ypos = Cos(angle/10,-100);
|
if (visible)
|
||||||
|
newvis = VIS_Owner;
|
||||||
|
else
|
||||||
|
newvis = VIS_None;
|
||||||
|
oldvis = this.Visibility;
|
||||||
|
this.Visibility = newvis;
|
||||||
|
return newvis != oldvis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func StartAim(object clonk, bool stealth, object GUImenu)
|
private func CreateMoveEffect(object clonk)
|
||||||
{
|
{
|
||||||
// only reinitialize angle if the crosshair hasn't been there before
|
crew = clonk;
|
||||||
if(!GetEffect("Move",this))
|
UpdatePosition();
|
||||||
{
|
RemoveEffect("Move",this);
|
||||||
// which should basically be only the case on the first time aiming
|
AddEffect("Move",this,1,1,this);
|
||||||
angle = 800*(clonk->GetDir()*2-1);
|
}
|
||||||
}
|
|
||||||
|
public func StartAim(object clonk, int default_angle, object GUImenu)
|
||||||
|
{
|
||||||
|
aiming = true;
|
||||||
|
|
||||||
// gui or landscape mode:
|
// gui or landscape mode:
|
||||||
if (GUImenu)
|
if (GUImenu)
|
||||||
{
|
{
|
||||||
|
@ -79,22 +96,12 @@ public func StartAim(object clonk, bool stealth, object GUImenu)
|
||||||
SetCategory(C4D_StaticBack | C4D_IgnoreFoW);
|
SetCategory(C4D_StaticBack | C4D_IgnoreFoW);
|
||||||
menu = nil;
|
menu = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set starting position for analog pad
|
|
||||||
UpdateAnalogpadPos();
|
|
||||||
|
|
||||||
crew = clonk;
|
|
||||||
UpdatePosition();
|
|
||||||
RemoveEffect("Move",this);
|
|
||||||
AddEffect("Move",this,1,1,this);
|
|
||||||
|
|
||||||
if(!stealth)
|
// Use the given angle if the player wasn't aiming before.
|
||||||
{
|
if (SetVisibility(true) && default_angle)
|
||||||
this["Visibility"] = VIS_Owner;
|
angle = default_angle;
|
||||||
crew->SetComDir(COMD_Stop);
|
|
||||||
aiming = true;
|
CreateMoveEffect(clonk);
|
||||||
EnableKeyAimControls(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func UpdatePosition()
|
private func UpdatePosition()
|
||||||
|
@ -112,65 +119,41 @@ private func UpdatePosition()
|
||||||
|
|
||||||
private func MirrorCursor()
|
private func MirrorCursor()
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
angle = -Normalize(angle,-1800,10);
|
angle = -Normalize(angle,-1800,10);
|
||||||
UpdateAnalogpadPos();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func StopAim()
|
public func StopAim()
|
||||||
{
|
{
|
||||||
RemoveEffect("Move",this);
|
|
||||||
this["Visibility"] = VIS_None;
|
|
||||||
dirx = 0;
|
|
||||||
diry = 0;
|
|
||||||
EnableKeyAimControls(false);
|
|
||||||
analogaim = false;
|
|
||||||
aiming = false;
|
aiming = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private func EnableKeyAimControls(bool enable)
|
// Aiming means that some object is currently actively using the crosshair.
|
||||||
{
|
|
||||||
SetPlayerControlEnabled(GetOwner(), CON_AimUp, enable);
|
|
||||||
SetPlayerControlEnabled(GetOwner(), CON_AimDown, enable);
|
|
||||||
SetPlayerControlEnabled(GetOwner(), CON_AimLeft, enable);
|
|
||||||
SetPlayerControlEnabled(GetOwner(), CON_AimRight, enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public func IsAiming()
|
public func IsAiming()
|
||||||
{
|
{
|
||||||
return aiming;
|
return aiming;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func Aim(int ctrl, object clonk, int strength, int repeat, int release)
|
// The crosshair is also active when the player is holding the aiming stick.
|
||||||
|
public func IsActive()
|
||||||
|
{
|
||||||
|
return aiming || Visible();
|
||||||
|
}
|
||||||
|
|
||||||
|
public func Aim(int ctrl, object clonk, int strength, int repeat, int status)
|
||||||
{
|
{
|
||||||
// start (stealth) aiming
|
// start (stealth) aiming
|
||||||
if(!GetEffect("Move",this))
|
if(!GetEffect("Move",this))
|
||||||
StartAim(clonk,true);
|
CreateMoveEffect(clonk);
|
||||||
|
|
||||||
// aiming with analog pad
|
// aiming with analog pad
|
||||||
if (ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight)
|
if (status == CONS_Moved &&
|
||||||
|
(ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight))
|
||||||
{
|
{
|
||||||
dirx = diry = 0;
|
|
||||||
|
|
||||||
if(ctrl == CON_AimAxisUp) ypos = -strength;
|
if(ctrl == CON_AimAxisUp) ypos = -strength;
|
||||||
if(ctrl == CON_AimAxisDown) ypos = strength;
|
if(ctrl == CON_AimAxisDown) ypos = strength;
|
||||||
if(ctrl == CON_AimAxisLeft) xpos = -strength;
|
if(ctrl == CON_AimAxisLeft) xpos = -strength;
|
||||||
if(ctrl == CON_AimAxisRight) xpos = strength;
|
if(ctrl == CON_AimAxisRight) xpos = strength;
|
||||||
analogaim = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// stop
|
|
||||||
else if (release && !analogaim)
|
|
||||||
{
|
|
||||||
if(ctrl == CON_AimUp || ctrl == CON_AimDown) diry = 0;
|
|
||||||
else if(ctrl == CON_AimLeft || ctrl == CON_AimRight) dirx = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(!release /*&& !repeat */ && !analogaim)
|
|
||||||
{
|
|
||||||
if(ctrl == CON_AimUp) diry = -1;
|
|
||||||
else if(ctrl == CON_AimDown) diry = 1;
|
|
||||||
else if(ctrl == CON_AimLeft) dirx = -1;
|
|
||||||
else if(ctrl == CON_AimRight) dirx = 1;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -46,6 +46,9 @@ static const ACTIONTYPE_EXTRA = 4;
|
||||||
// elevators within this range (x) can be called
|
// elevators within this range (x) can be called
|
||||||
static const ELEVATOR_CALL_DISTANCE = 30;
|
static const ELEVATOR_CALL_DISTANCE = 30;
|
||||||
|
|
||||||
|
// default throwing angle used while the Clonk isn't aiming
|
||||||
|
static const DEFAULT_THROWING_ANGLE = 500;
|
||||||
|
|
||||||
/* ++++++++++++++++++++++++ Clonk Inventory Control ++++++++++++++++++++++++ */
|
/* ++++++++++++++++++++++++ Clonk Inventory Control ++++++++++++++++++++++++ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -178,13 +181,13 @@ public func GetExtraInteractions()
|
||||||
/* +++++++++++++++++++++++++++ Clonk Control +++++++++++++++++++++++++++ */
|
/* +++++++++++++++++++++++++++ Clonk Control +++++++++++++++++++++++++++ */
|
||||||
|
|
||||||
/* Main control function */
|
/* Main control function */
|
||||||
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
if (!this)
|
if (!this)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Contents menu
|
// Contents menu
|
||||||
if (ctrl == CON_Contents && !release)
|
if (ctrl == CON_Contents && status == CONS_Down)
|
||||||
{
|
{
|
||||||
// Close any menu if open.
|
// Close any menu if open.
|
||||||
if (GetMenu())
|
if (GetMenu())
|
||||||
|
@ -221,10 +224,11 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
else ctrl = CON_Use;
|
else ctrl = CON_Use;
|
||||||
|
|
||||||
repeat = true;
|
repeat = true;
|
||||||
release = false;
|
status = CONS_Down;
|
||||||
}
|
}
|
||||||
// controls except a few reset a previously given command
|
// controls except a few reset a previously given command
|
||||||
else SetCommand("None");
|
else if (status != CONS_Moved)
|
||||||
|
SetCommand("None");
|
||||||
|
|
||||||
/* aiming with analog pad or keys:
|
/* aiming with analog pad or keys:
|
||||||
This works completely different. There are CON_AimAxis* and CON_Aim*,
|
This works completely different. There are CON_AimAxis* and CON_Aim*,
|
||||||
|
@ -238,23 +242,29 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
CON_Left is still called afterwards. So if the clonk finally starts to
|
CON_Left is still called afterwards. So if the clonk finally starts to
|
||||||
aim, the virtual cursor already aims into the direction in which he ran
|
aim, the virtual cursor already aims into the direction in which he ran
|
||||||
*/
|
*/
|
||||||
if (ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight
|
if (ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight)
|
||||||
|| ctrl == CON_AimUp || ctrl == CON_AimDown || ctrl == CON_AimLeft || ctrl == CON_AimRight)
|
|
||||||
{
|
{
|
||||||
var success = VirtualCursor()->Aim(ctrl,this,strength,repeat,release);
|
var success = VirtualCursor()->Aim(ctrl,this,strength,repeat,status);
|
||||||
// in any case, CON_Aim* is called but it is only successful if the virtual cursor is aiming
|
// in any case, CON_Aim* is called but it is only successful if the virtual cursor is aiming
|
||||||
return success && VirtualCursor()->IsAiming();
|
return success && VirtualCursor()->IsAiming();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simulate a mouse cursor for gamepads.
|
||||||
|
if (HasVirtualCursor())
|
||||||
|
{
|
||||||
|
x = this.control.mlastx;
|
||||||
|
y = this.control.mlasty;
|
||||||
|
}
|
||||||
|
|
||||||
// save last mouse position:
|
// save last mouse position:
|
||||||
// if the using has to be canceled, no information about the current x,y
|
// if the using has to be canceled, no information about the current x,y
|
||||||
// is available. Thus, the last x,y position needs to be saved
|
// is available. Thus, the last x,y position needs to be saved
|
||||||
if (ctrl == CON_Use || ctrl == CON_UseAlt)
|
else if (ctrl == CON_Use || ctrl == CON_UseAlt)
|
||||||
{
|
{
|
||||||
this.control.mlastx = x;
|
this.control.mlastx = x;
|
||||||
this.control.mlasty = y;
|
this.control.mlasty = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
var proc = GetProcedure();
|
var proc = GetProcedure();
|
||||||
|
|
||||||
// building, vehicle, mount, contents, menu control
|
// building, vehicle, mount, contents, menu control
|
||||||
|
@ -269,23 +279,23 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
// menu
|
// menu
|
||||||
if (this.control.menu)
|
if (this.control.menu)
|
||||||
{
|
{
|
||||||
return Control2Menu(ctrl, x,y,strength, repeat, release);
|
return Control2Menu(ctrl, x,y,strength, repeat, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
var contents = this->GetHandItem(0);
|
var contents = this->GetHandItem(0);
|
||||||
|
|
||||||
// usage
|
// usage
|
||||||
var use = (ctrl == CON_Use || ctrl == CON_UseDelayed || ctrl == CON_UseAlt || ctrl == CON_UseAltDelayed);
|
var use = (ctrl == CON_Use || ctrl == CON_UseAlt);
|
||||||
if (use)
|
if (use)
|
||||||
{
|
{
|
||||||
if (house)
|
if (house)
|
||||||
{
|
{
|
||||||
return ControlUse2Script(ctrl, x, y, strength, repeat, release, house);
|
return ControlUse2Script(ctrl, x, y, strength, repeat, status, house);
|
||||||
}
|
}
|
||||||
// control to grabbed vehicle
|
// control to grabbed vehicle
|
||||||
else if (vehicle && proc == "PUSH")
|
else if (vehicle && proc == "PUSH")
|
||||||
{
|
{
|
||||||
return ControlUse2Script(ctrl, x, y, strength, repeat, release, vehicle);
|
return ControlUse2Script(ctrl, x, y, strength, repeat, status, vehicle);
|
||||||
}
|
}
|
||||||
else if (vehicle && proc == "ATTACH")
|
else if (vehicle && proc == "ATTACH")
|
||||||
{
|
{
|
||||||
|
@ -301,25 +311,25 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
usage via CancelUse().
|
usage via CancelUse().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ControlUse2Script(ctrl, x, y, strength, repeat, release, vehicle))
|
if (ControlUse2Script(ctrl, x, y, strength, repeat, status, vehicle))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// handled if the horse is the used object
|
// handled if the horse is the used object
|
||||||
// ("using" is set to the object in StartUse(Delayed)Control - when the
|
// ("using" is set to the object in StartUseControl - when the
|
||||||
// object returns true on that callback. Exactly what we want)
|
// object returns true on that callback. Exactly what we want)
|
||||||
if (this.control.current_object == vehicle) return true;
|
if (this.control.current_object == vehicle) return true;
|
||||||
// has been cancelled (it is not the start of the usage but no object is used)
|
// has been cancelled (it is not the start of the usage but no object is used)
|
||||||
if (!this.control.current_object && (repeat || release)) return true;
|
if (!this.control.current_object && (repeat || status == CONS_Up)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// releasing the use-key always cancels shelved commands (in that case no this.control.current_object exists)
|
// releasing the use-key always cancels shelved commands (in that case no this.control.current_object exists)
|
||||||
if(release) StopShelvedCommand();
|
if(status == CONS_Up) StopShelvedCommand();
|
||||||
// Release commands are always forwarded even if contents is 0, in case we
|
// Release commands are always forwarded even if contents is 0, in case we
|
||||||
// need to cancel use of an object that left inventory
|
// need to cancel use of an object that left inventory
|
||||||
if (contents || (release && this.control.current_object))
|
if (contents || (status == CONS_Up && this.control.current_object))
|
||||||
{
|
{
|
||||||
if (ControlUse2Script(ctrl, x, y, strength, repeat, release, contents))
|
if (ControlUse2Script(ctrl, x, y, strength, repeat, status, contents))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +337,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
// A click on throw can also just abort usage without having any other effects.
|
// A click on throw can also just abort usage without having any other effects.
|
||||||
// todo: figure out if wise.
|
// todo: figure out if wise.
|
||||||
var currently_in_use = this.control.current_object != nil;
|
var currently_in_use = this.control.current_object != nil;
|
||||||
if ((ctrl == CON_Throw || ctrl == CON_ThrowDelayed) && currently_in_use && !release)
|
if (ctrl == CON_Throw && currently_in_use && status == CONS_Down)
|
||||||
{
|
{
|
||||||
CancelUse();
|
CancelUse();
|
||||||
return true;
|
return true;
|
||||||
|
@ -336,7 +346,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
// Throwing and dropping
|
// Throwing and dropping
|
||||||
// only if not in house, not grabbing a vehicle and an item selected
|
// only if not in house, not grabbing a vehicle and an item selected
|
||||||
// only act on press, not release
|
// only act on press, not release
|
||||||
if ((ctrl == CON_Throw || ctrl == CON_ThrowDelayed) && !house && (!vehicle || proc == "ATTACH" || proc == "PUSH") && !release)
|
if (ctrl == CON_Throw && !house && (!vehicle || proc == "ATTACH" || proc == "PUSH") && status == CONS_Down)
|
||||||
{
|
{
|
||||||
if (contents)
|
if (contents)
|
||||||
{
|
{
|
||||||
|
@ -365,33 +375,19 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
if (only_drop || Distance(0, 0, x, y) < 10 || (Abs(x) < 10 && y > 10))
|
if (only_drop || Distance(0, 0, x, y) < 10 || (Abs(x) < 10 && y > 10))
|
||||||
only_drop = true;
|
only_drop = true;
|
||||||
// throw
|
// throw
|
||||||
if (ctrl == CON_Throw)
|
CancelUse();
|
||||||
|
|
||||||
|
if (only_drop)
|
||||||
|
return ObjectCommand("Drop", contents);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
CancelUse();
|
if (HasVirtualCursor() && !VirtualCursor()->IsActive())
|
||||||
|
|
||||||
if (only_drop)
|
|
||||||
return ObjectCommand("Drop", contents);
|
|
||||||
else
|
|
||||||
return ObjectCommand("Throw", contents, x, y);
|
|
||||||
}
|
|
||||||
// throw delayed
|
|
||||||
if (ctrl == CON_ThrowDelayed)
|
|
||||||
{
|
|
||||||
CancelUse();
|
|
||||||
if (release)
|
|
||||||
{
|
{
|
||||||
VirtualCursor()->StopAim();
|
var angle = DEFAULT_THROWING_ANGLE * (GetDir()*2 - 1);
|
||||||
|
x = +Sin(angle, CURSOR_Radius, 10);
|
||||||
if (only_drop)
|
y = -Cos(angle, CURSOR_Radius, 10);
|
||||||
return ObjectCommand("Drop", contents);
|
|
||||||
else
|
|
||||||
return ObjectCommand("Throw", contents, this.control.mlastx, this.control.mlasty);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VirtualCursor()->StartAim(this);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return ObjectCommand("Throw", contents, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,14 +398,14 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
// forward to script...
|
// forward to script...
|
||||||
if (house)
|
if (house)
|
||||||
{
|
{
|
||||||
return ControlMovement2Script(ctrl, x, y, strength, repeat, release, house);
|
return ControlMovement2Script(ctrl, x, y, strength, repeat, status, house);
|
||||||
}
|
}
|
||||||
else if (vehicle)
|
else if (vehicle)
|
||||||
{
|
{
|
||||||
if (ControlMovement2Script(ctrl, x, y, strength, repeat, release, vehicle)) return true;
|
if (ControlMovement2Script(ctrl, x, y, strength, repeat, status, vehicle)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ObjectControlMovement(plr, ctrl, strength, release);
|
return ObjectControlMovement(plr, ctrl, strength, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a roll on landing or when standing. This means that the CON_Down was not handled previously.
|
// Do a roll on landing or when standing. This means that the CON_Down was not handled previously.
|
||||||
|
@ -433,7 +429,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
// Fall through half-solid mask
|
// Fall through half-solid mask
|
||||||
if (ctrl == CON_FallThrough)
|
if (ctrl == CON_FallThrough)
|
||||||
{
|
{
|
||||||
if(!release)
|
if(status == CONS_Down)
|
||||||
{
|
{
|
||||||
if (this->IsWalking())
|
if (this->IsWalking())
|
||||||
{
|
{
|
||||||
|
@ -469,7 +465,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unhandled control
|
// Unhandled control
|
||||||
return _inherited(plr, ctrl, x, y, strength, repeat, release, ...);
|
return _inherited(plr, ctrl, x, y, strength, repeat, status, ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A wrapper to SetCommand to catch special behaviour for some actions.
|
// A wrapper to SetCommand to catch special behaviour for some actions.
|
||||||
|
@ -617,18 +613,12 @@ func CanReIssueCommand(proplist data)
|
||||||
|
|
||||||
if(data.ctrl == CON_Use)
|
if(data.ctrl == CON_Use)
|
||||||
return !data.obj->~RejectUse(this);
|
return !data.obj->~RejectUse(this);
|
||||||
|
|
||||||
if(data.ctrl == CON_UseDelayed)
|
|
||||||
return !data.obj->~RejectUse(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReIssueCommand(proplist data)
|
func ReIssueCommand(proplist data)
|
||||||
{
|
{
|
||||||
if(data.ctrl == CON_Use)
|
if(data.ctrl == CON_Use)
|
||||||
return StartUseControl(data.ctrl, this.control.mlastx, this.control.mlasty, data.obj);
|
return StartUseControl(data.ctrl, this.control.mlastx, this.control.mlasty, data.obj);
|
||||||
|
|
||||||
if(data.ctrl == CON_UseDelayed)
|
|
||||||
return StartUseDelayedControl(data.ctrl, data.obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartUseControl(int ctrl, int x, int y, object obj)
|
func StartUseControl(int ctrl, int x, int y, object obj)
|
||||||
|
@ -651,6 +641,17 @@ func StartUseControl(int ctrl, int x, int y, object obj)
|
||||||
this.control.using_type = DetermineUsageType(obj);
|
this.control.using_type = DetermineUsageType(obj);
|
||||||
this.control.alt = ctrl != CON_Use;
|
this.control.alt = ctrl != CON_Use;
|
||||||
|
|
||||||
|
if (HasVirtualCursor())
|
||||||
|
{
|
||||||
|
var cursor = VirtualCursor(), angle;
|
||||||
|
if (!cursor->IsActive() && (angle = obj->~DefaultCrosshairAngle(this, GetDir()*2 - 1)))
|
||||||
|
{
|
||||||
|
x = +Sin(angle, CURSOR_Radius, 10);
|
||||||
|
y = -Cos(angle, CURSOR_Radius, 10);
|
||||||
|
}
|
||||||
|
cursor->StartAim(this, angle);
|
||||||
|
}
|
||||||
|
|
||||||
var hold_enabled = obj->Call("~HoldingEnabled");
|
var hold_enabled = obj->Call("~HoldingEnabled");
|
||||||
|
|
||||||
if (hold_enabled)
|
if (hold_enabled)
|
||||||
|
@ -687,37 +688,6 @@ func StartUseControl(int ctrl, int x, int y, object obj)
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartUseDelayedControl(int ctrl, object obj)
|
|
||||||
{
|
|
||||||
this.control.started_use = false;
|
|
||||||
|
|
||||||
if(obj->~RejectUse(this))
|
|
||||||
{
|
|
||||||
// remember for later:
|
|
||||||
ShelveCommand(this, "CanReIssueCommand", this, "ReIssueCommand", {obj = obj, ctrl = ctrl});
|
|
||||||
// but still catch command
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable climb/hangle actions for the duration of this use
|
|
||||||
if (obj.ForceFreeHands && !GetEffect("IntControlFreeHands", this)) AddEffect("IntControlFreeHands", this, 130, 0, this);
|
|
||||||
|
|
||||||
this.control.current_object = obj;
|
|
||||||
this.control.using_type = DetermineUsageType(obj);
|
|
||||||
this.control.alt = ctrl != CON_UseDelayed;
|
|
||||||
|
|
||||||
VirtualCursor()->StartAim(this);
|
|
||||||
|
|
||||||
// call UseStart
|
|
||||||
var handled = obj->Call(GetUseCallString("Start"),this,this.control.mlastx,this.control.mlasty);
|
|
||||||
this.control.noholdingcallbacks = !handled;
|
|
||||||
|
|
||||||
if(handled)
|
|
||||||
this.control.started_use = true;
|
|
||||||
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
func CancelUseControl(int x, int y)
|
func CancelUseControl(int x, int y)
|
||||||
{
|
{
|
||||||
// forget possibly stored commands
|
// forget possibly stored commands
|
||||||
|
@ -782,11 +752,6 @@ func HoldingUseControl(int ctrl, int x, int y, object obj)
|
||||||
{
|
{
|
||||||
var mex = x;
|
var mex = x;
|
||||||
var mey = y;
|
var mey = y;
|
||||||
if (ctrl == CON_UseDelayed || ctrl == CON_UseAltDelayed)
|
|
||||||
{
|
|
||||||
mex = this.control.mlastx;
|
|
||||||
mey = this.control.mlasty;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Message("%d,%d",this,mex,mey);
|
//Message("%d,%d",this,mex,mey);
|
||||||
|
|
||||||
|
@ -829,29 +794,6 @@ func HoldingUseControl(int ctrl, int x, int y, object obj)
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
func StopUseDelayedControl(object obj)
|
|
||||||
{
|
|
||||||
// ControlUseStop, ControlUseAltStop, ContainedUseAltStop, etc...
|
|
||||||
var handled = obj->Call(GetUseCallString("Stop"), this, this.control.mlastx, this.control.mlasty);
|
|
||||||
if (!handled)
|
|
||||||
handled = obj->Call(GetUseCallString(), this, this.control.mlastx, this.control.mlasty);
|
|
||||||
|
|
||||||
if (obj == this.control.current_object)
|
|
||||||
{
|
|
||||||
VirtualCursor()->StopAim();
|
|
||||||
// see StopUseControl
|
|
||||||
if(handled != -1)
|
|
||||||
{
|
|
||||||
this.control.current_object = nil;
|
|
||||||
this.control.using_type = nil;
|
|
||||||
this.control.alt = false;
|
|
||||||
}
|
|
||||||
this.control.noholdingcallbacks = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// very infrequent timer to prevent dangling effects, this is not necessary for correct functioning
|
// very infrequent timer to prevent dangling effects, this is not necessary for correct functioning
|
||||||
func FxItemRemovalCheckTimer(object target, proplist effect, int time)
|
func FxItemRemovalCheckTimer(object target, proplist effect, int time)
|
||||||
{
|
{
|
||||||
|
@ -876,43 +818,31 @@ func FxItemRemovalCheckStop(object target, proplist effect, int reason, bool tem
|
||||||
|
|
||||||
|
|
||||||
// Control use redirected to script
|
// Control use redirected to script
|
||||||
func ControlUse2Script(int ctrl, int x, int y, int strength, bool repeat, bool release, object obj)
|
func ControlUse2Script(int ctrl, int x, int y, int strength, bool repeat, int status, object obj)
|
||||||
{
|
{
|
||||||
// standard use
|
// standard use
|
||||||
if (ctrl == CON_Use || ctrl == CON_UseAlt)
|
if (ctrl == CON_Use || ctrl == CON_UseAlt)
|
||||||
{
|
{
|
||||||
if (!release && !repeat)
|
if (status == CONS_Down && !repeat)
|
||||||
{
|
{
|
||||||
return StartUseControl(ctrl,x, y, obj);
|
return StartUseControl(ctrl,x, y, obj);
|
||||||
}
|
}
|
||||||
else if (release && (obj == this.control.current_object || obj == GetActionTarget()))
|
else if (status == CONS_Up && (obj == this.control.current_object || obj == GetActionTarget()))
|
||||||
{
|
{
|
||||||
return StopUseControl(x, y, obj);
|
return StopUseControl(x, y, obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// gamepad use
|
|
||||||
else if (ctrl == CON_UseDelayed || ctrl == CON_UseAltDelayed)
|
|
||||||
{
|
|
||||||
if (!release && !repeat)
|
|
||||||
{
|
|
||||||
return StartUseDelayedControl(ctrl, obj);
|
|
||||||
}
|
|
||||||
else if (release && (obj == this.control.current_object || obj == GetActionTarget()))
|
|
||||||
{
|
|
||||||
return StopUseDelayedControl(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// more use (holding)
|
// more use (holding)
|
||||||
if (ctrl == CON_Use || ctrl == CON_UseAlt || ctrl == CON_UseDelayed || ctrl == CON_UseAltDelayed)
|
if (ctrl == CON_Use || ctrl == CON_UseAlt)
|
||||||
{
|
{
|
||||||
if (release)
|
if (status == CONS_Up)
|
||||||
{
|
{
|
||||||
// leftover use release
|
// leftover use release
|
||||||
CancelUse();
|
CancelUse();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (repeat && !this.control.noholdingcallbacks)
|
else if (status == CONS_Down && repeat && !this.control.noholdingcallbacks)
|
||||||
{
|
{
|
||||||
return HoldingUseControl(ctrl, x, y, obj);
|
return HoldingUseControl(ctrl, x, y, obj);
|
||||||
}
|
}
|
||||||
|
@ -922,7 +852,7 @@ func ControlUse2Script(int ctrl, int x, int y, int strength, bool repeat, bool r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control use redirected to script
|
// Control use redirected to script
|
||||||
func ControlMovement2Script(int ctrl, int x, int y, int strength, bool repeat, bool release, object obj)
|
func ControlMovement2Script(int ctrl, int x, int y, int strength, bool repeat, int status, object obj)
|
||||||
{
|
{
|
||||||
// overloads of movement commandos
|
// overloads of movement commandos
|
||||||
if (ctrl == CON_Left || ctrl == CON_Right || ctrl == CON_Down || ctrl == CON_Up || ctrl == CON_Jump)
|
if (ctrl == CON_Left || ctrl == CON_Right || ctrl == CON_Down || ctrl == CON_Up || ctrl == CON_Jump)
|
||||||
|
@ -931,7 +861,7 @@ func ControlMovement2Script(int ctrl, int x, int y, int strength, bool repeat, b
|
||||||
if (Contained() == obj)
|
if (Contained() == obj)
|
||||||
control_string = "Contained";
|
control_string = "Contained";
|
||||||
|
|
||||||
if (release)
|
if (status == CONS_Up)
|
||||||
{
|
{
|
||||||
// if any movement key has been released, ControlStop is called
|
// if any movement key has been released, ControlStop is called
|
||||||
if (obj->Call(Format("~%sStop", control_string), this, ctrl))
|
if (obj->Call(Format("~%sStop", control_string), this, ctrl))
|
||||||
|
@ -1040,7 +970,7 @@ func SetMenu(new_menu, bool unclosable)
|
||||||
SetComDir(COMD_Stop);
|
SetComDir(COMD_Stop);
|
||||||
|
|
||||||
if (PlayerHasVirtualCursor(GetOwner()))
|
if (PlayerHasVirtualCursor(GetOwner()))
|
||||||
VirtualCursor()->StartAim(this,false, new_menu);
|
VirtualCursor()->StartAim(this, 0, new_menu);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (GetType(new_menu) == C4V_C4Object && new_menu->~CursorUpdatesEnabled())
|
if (GetType(new_menu) == C4V_C4Object && new_menu->~CursorUpdatesEnabled())
|
||||||
|
|
|
@ -19,12 +19,12 @@ local virtual_cursor;
|
||||||
|
|
||||||
/* This part of gamepad control handles only object-style menus.
|
/* This part of gamepad control handles only object-style menus.
|
||||||
Fullscreen menus are handled differently. */
|
Fullscreen menus are handled differently. */
|
||||||
func Control2Menu(int ctrl, int x, int y, int strength, bool repeat, bool release)
|
func Control2Menu(int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* all this stuff is already done on a higher layer - in playercontrol.c
|
/* all this stuff is already done on a higher layer - in playercontrol.c
|
||||||
now this is just the same for gamepad control */
|
now this is just the same for gamepad control */
|
||||||
if (!PlayerHasVirtualCursor(GetOwner()))
|
if (!HasVirtualCursor())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!this->GetMenu()) return false;
|
if (!this->GetMenu()) return false;
|
||||||
|
@ -36,27 +36,27 @@ func Control2Menu(int ctrl, int x, int y, int strength, bool repeat, bool releas
|
||||||
// update angle for visual effect on the menu
|
// update angle for visual effect on the menu
|
||||||
if (repeat)
|
if (repeat)
|
||||||
{
|
{
|
||||||
if (ctrl == CON_UseDelayed || ctrl == CON_UseAltDelayed)
|
if (ctrl == CON_Use || ctrl == CON_UseAlt)
|
||||||
this->GetMenu()->~UpdateCursor(mex,mey);
|
this->GetMenu()->~UpdateCursor(mex,mey);
|
||||||
}
|
}
|
||||||
// click on menu
|
// click on menu
|
||||||
if (release)
|
if (status == CONS_Up)
|
||||||
{
|
{
|
||||||
// select
|
// select
|
||||||
if (ctrl == CON_UseDelayed)
|
if (ctrl == CON_Use)
|
||||||
this->GetMenu()->~OnMouseClick(mex,mey);
|
this->GetMenu()->~OnMouseClick(mex,mey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ObjectControlMovement(int plr, int ctrl, int strength, bool release)
|
public func ObjectControlMovement(int plr, int ctrl, int strength, int status)
|
||||||
{
|
{
|
||||||
// from PlayerControl.c
|
// from PlayerControl.c
|
||||||
var result = inherited(plr,ctrl,strength,release,...);
|
var result = inherited(plr,ctrl,strength,status,...);
|
||||||
|
|
||||||
// do the following only if strength >= CON_Gamepad_Deadzone
|
// do the following only if strength >= CON_Gamepad_Deadzone
|
||||||
if(!release)
|
if(status == CONS_Down)
|
||||||
if(strength != nil && strength < CON_Gamepad_Deadzone)
|
if(strength != nil && strength < CON_Gamepad_Deadzone)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ public func ObjectControlMovement(int plr, int ctrl, int strength, bool release)
|
||||||
if(!virtual_cursor) return result;
|
if(!virtual_cursor) return result;
|
||||||
|
|
||||||
// change direction of virtual_cursor
|
// change direction of virtual_cursor
|
||||||
if(!release)
|
if(status == CONS_Down)
|
||||||
virtual_cursor->Direction(ctrl);
|
virtual_cursor->Direction(ctrl);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -79,7 +79,7 @@ func ReinitializeControls()
|
||||||
// if is aiming or in menu and no virtual cursor is there, create one
|
// if is aiming or in menu and no virtual cursor is there, create one
|
||||||
if (!virtual_cursor)
|
if (!virtual_cursor)
|
||||||
if (this.menu || this.control.current_object) // properties declared in ClonkControl.ocd
|
if (this.menu || this.control.current_object) // properties declared in ClonkControl.ocd
|
||||||
VirtualCursor()->StartAim(this,false,this.menu);
|
VirtualCursor()->StartAim(this,0,this.menu);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -91,6 +91,9 @@ func ReinitializeControls()
|
||||||
|
|
||||||
/* Virtual cursor stuff */
|
/* Virtual cursor stuff */
|
||||||
|
|
||||||
|
// Helper function.
|
||||||
|
private func HasVirtualCursor() { return PlayerHasVirtualCursor(GetOwner()); }
|
||||||
|
|
||||||
// get virtual cursor, if noone is there, create it
|
// get virtual cursor, if noone is there, create it
|
||||||
private func VirtualCursor()
|
private func VirtualCursor()
|
||||||
{
|
{
|
||||||
|
@ -122,19 +125,12 @@ public func UpdateVirtualCursorPos()
|
||||||
|
|
||||||
public func TriggerHoldingControl()
|
public func TriggerHoldingControl()
|
||||||
{
|
{
|
||||||
// using has been commented because it must be possible to use the virtual
|
if (this.control.current_object && !this.control.noholdingcallbacks)
|
||||||
// cursor aim also without a used object - for menus
|
|
||||||
// However, I think the check for 'this.control.current_object' here is just an unecessary safeguard
|
|
||||||
// since there is always a using-object if the clonk is aiming for a throw
|
|
||||||
// or a use. If the clonk uses it, there will be callbacks that cancel the
|
|
||||||
// callbacks to the virtual cursor
|
|
||||||
// - Newton
|
|
||||||
if (/*this.control.current_object && */!this.control.noholdingcallbacks)
|
|
||||||
{
|
{
|
||||||
var ctrl = CON_UseDelayed;
|
var ctrl = CON_Use;
|
||||||
if (this.control.alt)
|
if (this.control.alt)
|
||||||
ctrl = CON_UseAltDelayed;
|
ctrl = CON_UseAlt;
|
||||||
ObjectControl(GetOwner(), ctrl, 0, 0, 0, true, false);
|
ObjectControl(GetOwner(), ctrl, 0, 0, 0, true, CONS_Down);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -143,4 +139,4 @@ func RemoveVirtualCursor()
|
||||||
{
|
{
|
||||||
if (virtual_cursor)
|
if (virtual_cursor)
|
||||||
virtual_cursor->StopAim();
|
virtual_cursor->StopAim();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,13 @@ public func OnShiftCursor(object new_cursor)
|
||||||
return _inherited(new_cursor, ...);
|
return _inherited(new_cursor, ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
if (!this)
|
if (!this)
|
||||||
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);
|
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);
|
||||||
|
|
||||||
// Begin interaction.
|
// Begin interaction.
|
||||||
if (ctrl == CON_Interact && !release)
|
if (ctrl == CON_Interact && status == CONS_Down)
|
||||||
{
|
{
|
||||||
this->CancelUse();
|
this->CancelUse();
|
||||||
BeginInteract();
|
BeginInteract();
|
||||||
|
@ -50,7 +50,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish picking up (aka "collect").
|
// Finish picking up (aka "collect").
|
||||||
if (ctrl == CON_Interact && release)
|
if (ctrl == CON_Interact && status == CONS_Up)
|
||||||
{
|
{
|
||||||
EndInteract();
|
EndInteract();
|
||||||
return true;
|
return true;
|
||||||
|
@ -71,7 +71,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);
|
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
private func FxIntHighlightInteractionStart(object target, proplist fx, temp, proplist interaction, proplist interaction_help)
|
private func FxIntHighlightInteractionStart(object target, proplist fx, temp, proplist interaction, proplist interaction_help)
|
||||||
|
|
|
@ -55,17 +55,17 @@ func RejectCollect(id objid, object obj)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
if (!this)
|
if (!this)
|
||||||
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);
|
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);
|
||||||
|
|
||||||
// Quickswitch changes the current active inventory slot
|
// Quickswitch changes the current active inventory slot
|
||||||
if (ctrl == CON_QuickSwitch && !release)
|
if (ctrl == CON_QuickSwitch && status == CONS_Down)
|
||||||
{
|
{
|
||||||
// but ignore quickswitch if we have more than 1 hand-slot
|
// but ignore quickswitch if we have more than 1 hand-slot
|
||||||
if(this.HandObjects > 1)
|
if(this.HandObjects > 1)
|
||||||
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);;
|
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);;
|
||||||
|
|
||||||
// A number key (hotkey) is pressed, change quick switch slot
|
// A number key (hotkey) is pressed, change quick switch slot
|
||||||
/*if (this.inventory.hotkey_down != nil)
|
/*if (this.inventory.hotkey_down != nil)
|
||||||
|
@ -78,7 +78,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
SetHandItemPos(0, this.inventory.quick_slot); // quick_slot is updated in SetHandItemPos
|
SetHandItemPos(0, this.inventory.quick_slot); // quick_slot is updated in SetHandItemPos
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ctrl == CON_QuickSwitch && release) // Do nothing for now but will be used in the future
|
if (ctrl == CON_QuickSwitch && status == CONS_Up) // Do nothing for now but will be used in the future
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
if (!Contained())
|
if (!Contained())
|
||||||
{
|
{
|
||||||
// Quick-pickup item via click? Note that this relies on being executed after the normal Clonk controls
|
// Quick-pickup item via click? Note that this relies on being executed after the normal Clonk controls
|
||||||
if (ctrl == CON_Use && !this->GetHandItem(0) && !release)
|
if (ctrl == CON_Use && !this->GetHandItem(0) && status == CONS_Down)
|
||||||
{
|
{
|
||||||
var sort = Sort_Distance(x, y);
|
var sort = Sort_Distance(x, y);
|
||||||
var items = FindAllPickupItems(sort);
|
var items = FindAllPickupItems(sort);
|
||||||
|
@ -97,7 +97,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin picking up objects.
|
// Begin picking up objects.
|
||||||
if (ctrl == CON_PickUp && !release)
|
if (ctrl == CON_PickUp && status == CONS_Down)
|
||||||
{
|
{
|
||||||
this->CancelUse();
|
this->CancelUse();
|
||||||
BeginPickingUp();
|
BeginPickingUp();
|
||||||
|
@ -105,7 +105,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop the mouse item?
|
// Drop the mouse item?
|
||||||
if (ctrl == CON_Drop && !release)
|
if (ctrl == CON_Drop && status == CONS_Down)
|
||||||
{
|
{
|
||||||
// Do not immediately collect another thing unless chosen with left/right.
|
// Do not immediately collect another thing unless chosen with left/right.
|
||||||
if (this.inventory.is_picking_up)
|
if (this.inventory.is_picking_up)
|
||||||
|
@ -139,7 +139,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish picking up (aka "collect").
|
// Finish picking up (aka "collect").
|
||||||
if (ctrl == CON_PickUp && release)
|
if (ctrl == CON_PickUp && status == CONS_Up)
|
||||||
{
|
{
|
||||||
EndPickingUp();
|
EndPickingUp();
|
||||||
return true;
|
return true;
|
||||||
|
@ -223,7 +223,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
if (this.inventory.hotkey_down != nil && hot > 0 && hot <= this.MaxContentsCount && this.inventory.hotkey_down != hot)
|
if (this.inventory.hotkey_down != nil && hot > 0 && hot <= this.MaxContentsCount && this.inventory.hotkey_down != hot)
|
||||||
{
|
{
|
||||||
// do nothing if this is just key down
|
// do nothing if this is just key down
|
||||||
if (!release)
|
if (status == CONS_Down)
|
||||||
return true;
|
return true;
|
||||||
// switch the two slots
|
// switch the two slots
|
||||||
this->~Switch2Items(this.inventory.hotkey_down-1, hot-1);
|
this->~Switch2Items(this.inventory.hotkey_down-1, hot-1);
|
||||||
|
@ -240,7 +240,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
}
|
}
|
||||||
|
|
||||||
// hotkey up: perform slot selection
|
// hotkey up: perform slot selection
|
||||||
if (hot > 0 && hot <= this.MaxContentsCount && release)
|
if (hot > 0 && hot <= this.MaxContentsCount && status == CONS_Up)
|
||||||
{
|
{
|
||||||
// This wasn't liked by many players, so slot selection is back to key down.
|
// This wasn't liked by many players, so slot selection is back to key down.
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// a hotkey is pressed, save it for now
|
// a hotkey is pressed, save it for now
|
||||||
if (hot > 0 && hot <= this.MaxContentsCount && !release)
|
if (hot > 0 && hot <= this.MaxContentsCount && status == CONS_Down)
|
||||||
{
|
{
|
||||||
this.inventory.hotkey_down = hot;
|
this.inventory.hotkey_down = hot;
|
||||||
// For safety
|
// For safety
|
||||||
|
@ -267,7 +267,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);
|
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
private func FxIntHighlightItemStart(object target, proplist fx, temp, object item)
|
private func FxIntHighlightItemStart(object target, proplist fx, temp, object item)
|
||||||
|
|
|
@ -83,12 +83,12 @@ public func FxControlConstructionPreviewStart(object clonk, effect, int temp, id
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by Control2Effect
|
// Called by Control2Effect
|
||||||
public func FxControlConstructionPreviewControl(object clonk, effect, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
public func FxControlConstructionPreviewControl(object clonk, effect, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
if (ctrl != CON_Aim)
|
if (ctrl != CON_Aim)
|
||||||
{
|
{
|
||||||
// CON_Use is accept, but don't remove the preview, this is done on releasing the button.
|
// CON_Use is accept, but don't remove the preview, this is done on releasing the button.
|
||||||
if (ctrl == CON_Use && !release)
|
if (ctrl == CON_Use && status == CONS_Down)
|
||||||
{
|
{
|
||||||
var ok = CreateConstructionSite(clonk, effect.structure, AbsX(effect.preview->GetX()), AbsY(effect.preview->GetY() + effect.preview.dimension_y/2), effect.preview.blocked, effect.preview.direction, effect.preview.stick_to);
|
var ok = CreateConstructionSite(clonk, effect.structure, AbsX(effect.preview->GetX()), AbsY(effect.preview->GetY() + effect.preview.dimension_y/2), effect.preview.blocked, effect.preview.direction, effect.preview.stick_to);
|
||||||
if (ok)
|
if (ok)
|
||||||
|
@ -105,7 +105,7 @@ public func FxControlConstructionPreviewControl(object clonk, effect, int ctrl,
|
||||||
// (yes, this means that actionbar-hotkeys wont work for it. However clicking the button will.)
|
// (yes, this means that actionbar-hotkeys wont work for it. However clicking the button will.)
|
||||||
else if (IsInteractionControl(ctrl))
|
else if (IsInteractionControl(ctrl))
|
||||||
{
|
{
|
||||||
if (release)
|
if (status == CONS_Up)
|
||||||
effect.preview->Flip();
|
effect.preview->Flip();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -337,13 +337,13 @@ public func FxIntClimbControlStop(object target, effect fx, int reason, bool tmp
|
||||||
return FX_OK;
|
return FX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func FxIntClimbControlControl(object target, effect fx, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
public func FxIntClimbControlControl(object target, effect fx, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
// Only handle movement controls.
|
// Only handle movement controls.
|
||||||
if (ctrl != CON_Up && ctrl != CON_Down && ctrl != CON_Right && ctrl != CON_Left)
|
if (ctrl != CON_Up && ctrl != CON_Down && ctrl != CON_Right && ctrl != CON_Left)
|
||||||
return false;
|
return false;
|
||||||
// Perform actions on key down and not on release.
|
// Perform actions on key down and not on release.
|
||||||
if (release)
|
if (status != CONS_Down)
|
||||||
return false;
|
return false;
|
||||||
// Move up and down by setting com dir.
|
// Move up and down by setting com dir.
|
||||||
if (ctrl == CON_Up)
|
if (ctrl == CON_Up)
|
||||||
|
|
|
@ -125,6 +125,11 @@ func PutLiquid(liquid_name, int amount, object source)
|
||||||
return after - before;
|
return after - before;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AcceptsLiquid(liquid_name, int amount)
|
||||||
|
{
|
||||||
|
return amount <= this->GetLiquidContainerMaxFillLevel() - GetLiquidAmount(liquid_name);
|
||||||
|
}
|
||||||
|
|
||||||
private func GetLiquidDef(liquid_name)
|
private func GetLiquidDef(liquid_name)
|
||||||
{
|
{
|
||||||
if (GetType(liquid_name) == C4V_String)
|
if (GetType(liquid_name) == C4V_String)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[DefCore]
|
||||||
|
id=Library_Wearable
|
||||||
|
Version=8,0
|
||||||
|
Category=C4D_StaticBack
|
|
@ -0,0 +1,180 @@
|
||||||
|
/**
|
||||||
|
Library_Wearable
|
||||||
|
Library for all clothing and other things worn on the clonk.
|
||||||
|
The library will make sure that not two objects are worn at the same
|
||||||
|
position at the same time.
|
||||||
|
|
||||||
|
@author: Clonkonaut
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Bone names of attachment on the clonk and also identifiers */
|
||||||
|
|
||||||
|
// Headwear like helmets, caps or similar
|
||||||
|
static const WEARABLE_Head = "skeleton_head";
|
||||||
|
|
||||||
|
local wear_effect;
|
||||||
|
|
||||||
|
local display_disabled = false;
|
||||||
|
|
||||||
|
/* Overloads */
|
||||||
|
|
||||||
|
// These functions must exist in order for this library to work
|
||||||
|
|
||||||
|
public func GetWearPlace()
|
||||||
|
{
|
||||||
|
return; // must return one of the WEARABLE_* constants
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other functions that can be present in the object:
|
||||||
|
|
||||||
|
func GetWearBone: return the bone with which it is attached to the clonk (default: "main")
|
||||||
|
func GetWearTransform(clonk): transformation added when worn
|
||||||
|
|
||||||
|
func StayAfterDeath: return true if the item should remain on the clonk after its death (default is that it does not stay)
|
||||||
|
|
||||||
|
func OnPutOn(clonk): callback after the item was put on
|
||||||
|
func OnTakenOff(clonk): callback after the item was taken off
|
||||||
|
|
||||||
|
func OnDamage(damage_amount, cause, by_player): Callback whenever the wearer is damaged, parameters are passed on from the effect Damage callback
|
||||||
|
Return value is returned (useful for protective clothing)
|
||||||
|
|
||||||
|
func GetCarryMode: must(!) return CARRY_None whenever display_disabled is true, otherwise display error will likely occur
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Engine Callbacks */
|
||||||
|
|
||||||
|
// It is assumed that a wearable must be contained in the clonk to be worn.
|
||||||
|
func Departure()
|
||||||
|
{
|
||||||
|
if (IsWorn())
|
||||||
|
TakeOff();
|
||||||
|
_inherited(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
func Destruction()
|
||||||
|
{
|
||||||
|
if (IsWorn())
|
||||||
|
TakeOff();
|
||||||
|
_inherited(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interface */
|
||||||
|
|
||||||
|
// The clonk will put on the item and take off any other item currently worn
|
||||||
|
// in the same place, unless no_force is true in which case false will be returned
|
||||||
|
// when something else is worn.
|
||||||
|
public func PutOn(object clonk, bool no_force)
|
||||||
|
{
|
||||||
|
// ???
|
||||||
|
if (!clonk->~IsClonk()) return false;
|
||||||
|
|
||||||
|
// Remove all other things before putting on
|
||||||
|
if (!no_force)
|
||||||
|
{
|
||||||
|
var effect;
|
||||||
|
for (var i = GetEffectCount("Wearing", clonk); effect = GetEffect("Wearing", clonk, i); i--)
|
||||||
|
if (effect.identifier == GetWearPlace())
|
||||||
|
RemoveEffect(nil, clonk, effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is not impossible that the item is currently held in the hand of the clonk.
|
||||||
|
// If so, temporarily disable display because the same mesh cannot be attached twice.
|
||||||
|
// Any item must adhere this variable in GetCarryMode!
|
||||||
|
display_disabled =true;
|
||||||
|
clonk->~UpdateAttach();
|
||||||
|
|
||||||
|
wear_effect = clonk->CreateEffect(Wearing, 2, nil, GetWearPlace(), this);
|
||||||
|
|
||||||
|
if (wear_effect == -1) // got rejected
|
||||||
|
wear_effect = nil;
|
||||||
|
|
||||||
|
display_disabled = false;
|
||||||
|
clonk->~UpdateAttach();
|
||||||
|
|
||||||
|
if (wear_effect)
|
||||||
|
{
|
||||||
|
// Callback to do whatever
|
||||||
|
this->~OnPutOn(clonk);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func IsWorn()
|
||||||
|
{
|
||||||
|
return wear_effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func TakeOff()
|
||||||
|
{
|
||||||
|
if (!wear_effect)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return RemoveEffect(nil, nil, wear_effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
func TakenOff()
|
||||||
|
{
|
||||||
|
wear_effect = nil;
|
||||||
|
if (Contained())
|
||||||
|
Contained()->~UpdateAttach();
|
||||||
|
// Callback to do whatever; note that at this point the item isn't necessary contained.
|
||||||
|
this->~OnTakenOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wearing effect */
|
||||||
|
|
||||||
|
local Wearing = new Effect {
|
||||||
|
Construction = func(string wearing_identifier, object worn_item) {
|
||||||
|
// Save where this thing is worn
|
||||||
|
this.identifier = wearing_identifier;
|
||||||
|
// Save what is worn
|
||||||
|
this.item = worn_item;
|
||||||
|
},
|
||||||
|
|
||||||
|
Start = func() {
|
||||||
|
// Check if parameters are properly set
|
||||||
|
if (this.identifier == nil) return -1;
|
||||||
|
if (this.item == nil) return -1;
|
||||||
|
|
||||||
|
var attachment_bone = this.item->~GetWearBone() ?? "main";
|
||||||
|
var attachment_transform = this.item->~GetWearTransform(this.Target);
|
||||||
|
|
||||||
|
this.attach = Target->AttachMesh(this.item, this.identifier, attachment_bone, attachment_transform);
|
||||||
|
},
|
||||||
|
|
||||||
|
Damage = func(int damage, int cause, int by_player) {
|
||||||
|
if (!this.item) return damage;
|
||||||
|
|
||||||
|
var ret = this.item->~OnDamage(damage, cause, by_player);
|
||||||
|
if (ret == nil)
|
||||||
|
ret = damage;
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
|
||||||
|
Effect = func(string new_name, var1) {
|
||||||
|
// Reject wearing effects if in the same place
|
||||||
|
if (new_name == "Wearing")
|
||||||
|
if (var1 == this.identifier)
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
Stop = func(int reason) {
|
||||||
|
// Items can prevent being removed from the clonk on death
|
||||||
|
if (reason == FX_Call_RemoveDeath)
|
||||||
|
if (this.item && this.item->~StayAfterDeath(this.Target))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (this.Target) this.Target->DetachMesh(this.attach);
|
||||||
|
this.attach = nil;
|
||||||
|
},
|
||||||
|
|
||||||
|
Destruction = func() {
|
||||||
|
if (this.attach != nil && this.Target)
|
||||||
|
this.Target->DetachMesh(this.attach);
|
||||||
|
if (this.item)
|
||||||
|
this.item->TakenOff();
|
||||||
|
}
|
||||||
|
};
|
|
@ -35,7 +35,7 @@ func OnClonkDeathEx(object clonk, int plr, int killed_by)
|
||||||
var which_one = Random(3) + 1;
|
var which_one = Random(3) + 1;
|
||||||
var log="";
|
var log="";
|
||||||
if (!GetPlayerName(killed_by))
|
if (!GetPlayerName(killed_by))
|
||||||
log=Format(Translate(Format("KilledByGaya%d", which_one)), GetTaggedPlayerName(plr), name);
|
log=Format(Translate(Format("KilledByGaia%d", which_one)), GetTaggedPlayerName(plr), name);
|
||||||
else if (plr == killed_by)
|
else if (plr == killed_by)
|
||||||
log=Format(Translate(Format("Selfkill%d", which_one)), GetTaggedPlayerName(plr), name);
|
log=Format(Translate(Format("Selfkill%d", which_one)), GetTaggedPlayerName(plr), name);
|
||||||
else if (!Hostile(plr,killed_by))
|
else if (!Hostile(plr,killed_by))
|
||||||
|
|
|
@ -7,9 +7,9 @@ Selfkill3=%s hat Selbstmord begangen! Der arme %s.
|
||||||
KilledByPlayer1=%s hat einen %s an %s verloren.
|
KilledByPlayer1=%s hat einen %s an %s verloren.
|
||||||
KilledByPlayer2=%ss %s konnte nichts gegen %s machen.
|
KilledByPlayer2=%ss %s konnte nichts gegen %s machen.
|
||||||
KilledByPlayer3=%s konnte mit seinem %s nicht gut genug kämpfen für %s.
|
KilledByPlayer3=%s konnte mit seinem %s nicht gut genug kämpfen für %s.
|
||||||
KilledByGaya1=%s hat einen %s weggezaubert bekommen.
|
KilledByGaia1=%s hat einen %s weggezaubert bekommen.
|
||||||
KilledByGaya2=%ss %s stirbt von alleine.
|
KilledByGaia2=%ss %s stirbt von alleine.
|
||||||
KilledByGaya3=%s hat einen %s an Gaya verloren.
|
KilledByGaia3=%s hat einen %s an Gaia verloren.
|
||||||
Teamkill1=%s hat einen %s an %s verloren. Teamkiller!
|
Teamkill1=%s hat einen %s an %s verloren. Teamkiller!
|
||||||
Teamkill2=%ss %s ist bei %s in Ungnade gefallen.
|
Teamkill2=%ss %s ist bei %s in Ungnade gefallen.
|
||||||
Teamkill3=%ss %s wurde von %s sauber hintergangen.
|
Teamkill3=%ss %s wurde von %s sauber hintergangen.
|
||||||
|
|
|
@ -7,9 +7,9 @@ Selfkill3=%s committed suicide! Poor %s.
|
||||||
KilledByPlayer1=%s has lost his %s to %s.
|
KilledByPlayer1=%s has lost his %s to %s.
|
||||||
KilledByPlayer2=%s's %s couldn't do anything against %s.
|
KilledByPlayer2=%s's %s couldn't do anything against %s.
|
||||||
KilledByPlayer3=%s's %s was not able to defeat %s.
|
KilledByPlayer3=%s's %s was not able to defeat %s.
|
||||||
KilledByGaya1=%s's %s was spirited away.
|
KilledByGaia1=%s's %s was spirited away.
|
||||||
KilledByGaya2=%s's %s died on its own.
|
KilledByGaia2=%s's %s died on its own.
|
||||||
KilledByGaya3=%s lost a %s to Gaya.
|
KilledByGaia3=%s lost a %s to Gaia.
|
||||||
Teamkill1=%s has lost a %s to %s. Teamkiller!
|
Teamkill1=%s has lost a %s to %s. Teamkiller!
|
||||||
Teamkill2=%s's %s fell out of %s's favour.
|
Teamkill2=%s's %s fell out of %s's favour.
|
||||||
Teamkill3=%s's %s was denied by %s.
|
Teamkill3=%s's %s was denied by %s.
|
||||||
|
|
|
@ -326,7 +326,6 @@ protected func Pumping()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stored_material_amount = i;
|
stored_material_amount = i;
|
||||||
if (stored_material_amount <= 0)
|
if (stored_material_amount <= 0)
|
||||||
stored_material_name = nil;
|
stored_material_name = nil;
|
||||||
|
@ -338,8 +337,8 @@ protected func Pumping()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Put into wait state if no liquid could be pumped for a while
|
// Put into wait state if no liquid could be pumped for a while or if the drain has no aperture, i.e. is a liquid tank.
|
||||||
if (++clog_count >= max_clog_count)
|
if (++clog_count >= max_clog_count || !drain_obj->~HasAperture())
|
||||||
{
|
{
|
||||||
SetState("WaitForLiquid");
|
SetState("WaitForLiquid");
|
||||||
}
|
}
|
||||||
|
@ -383,7 +382,6 @@ func InsertMaterialAtDrain(object drain_obj, string material_name, int amount)
|
||||||
drain_obj->InsertMaterial(material_index, drain_obj.ApertureOffsetX, drain_obj.ApertureOffsetY);
|
drain_obj->InsertMaterial(material_index, drain_obj.ApertureOffsetX, drain_obj.ApertureOffsetY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return amount <= 0;
|
return amount <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,9 +401,10 @@ func CheckState()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// can pump but has no liquid -> wait for liquid
|
// Can pump but has no liquid or can't dispense liquid -> wait.
|
||||||
var source_ok = IsLiquidSourceOk();
|
var source_mat = GetLiquidSourceMaterial();
|
||||||
var drain_ok = IsLiquidDrainOk();
|
var source_ok = source_mat != nil;
|
||||||
|
var drain_ok = GetLiquidDrainOk(source_mat);
|
||||||
if (!source_ok || !drain_ok)
|
if (!source_ok || !drain_ok)
|
||||||
{
|
{
|
||||||
if (!source_ok)
|
if (!source_ok)
|
||||||
|
@ -532,30 +531,39 @@ private func PumpHeight2Power(int pump_height)
|
||||||
return used_power;
|
return used_power;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check usage of this, probably has to return true if the source is a container
|
|
||||||
// Returns whether there is liquid at the source pipe to pump.
|
// Returns whether there is liquid at the source pipe to pump.
|
||||||
private func IsLiquidSourceOk()
|
private func GetLiquidSourceMaterial()
|
||||||
{
|
{
|
||||||
// source
|
// Get the source object and check whether there is liquid.
|
||||||
|
// TODO: If the source is a liquid container check which material will be supplied.
|
||||||
var source_obj = GetSourceObject();
|
var source_obj = GetSourceObject();
|
||||||
if(!source_obj->GBackLiquid(source_obj.ApertureOffsetX, source_obj.ApertureOffsetY))
|
var is_liquid = source_obj->GBackLiquid(source_obj.ApertureOffsetX, source_obj.ApertureOffsetY);
|
||||||
|
var liquid = MaterialName(source_obj->GetMaterial(source_obj.ApertureOffsetX, source_obj.ApertureOffsetY));
|
||||||
|
if (!is_liquid)
|
||||||
{
|
{
|
||||||
source_obj->~CycleApertureOffset(this); // try different offsets, so we can resume pumping after clog because 1px of earth was dropped on the source pipe
|
// Try different offsets, so we can resume pumping after clog because 1px of earth was dropped on the source pipe.
|
||||||
return false;
|
source_obj->~CycleApertureOffset(this);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return true;
|
return liquid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check usage of this, probably has to return true if the drain is a container
|
// Returns whether the drain pipe is free or the liquid container accepts the given material.
|
||||||
// Returns whether the drain pipe is free.
|
private func GetLiquidDrainOk(string liquid)
|
||||||
private func IsLiquidDrainOk()
|
|
||||||
{
|
{
|
||||||
// target (test with the very popular liquid "water")
|
|
||||||
var drain_obj = GetDrainObject();
|
var drain_obj = GetDrainObject();
|
||||||
if(!drain_obj->CanInsertMaterial(Material("Water"),drain_obj.ApertureOffsetX, drain_obj.ApertureOffsetY))
|
if (drain_obj->~HasAperture())
|
||||||
{
|
{
|
||||||
drain_obj->~CycleApertureOffset(this); // try different offsets, so we can resume pumping after clog because 1px of earth was dropped on the source pipe
|
if (!drain_obj->CanInsertMaterial(Material(liquid), drain_obj.ApertureOffsetX, drain_obj.ApertureOffsetY))
|
||||||
return false;
|
{
|
||||||
|
drain_obj->~CycleApertureOffset(this); // try different offsets, so we can resume pumping after clog because 1px of earth was dropped on the source pipe
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (drain_obj->~IsLiquidContainer())
|
||||||
|
{
|
||||||
|
if (!drain_obj->AcceptsLiquid(liquid, 1))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Name=Kokosnussbaum
|
Name=Kokospalme
|
|
@ -1 +1 @@
|
||||||
Name=Coconut Tree
|
Name=Coconut Palm
|
|
@ -1,7 +1,7 @@
|
||||||
[Material]
|
[Material]
|
||||||
Name=Brick
|
Name=Brick
|
||||||
Shape=Smoother
|
Shape=Smoother
|
||||||
Density=50
|
Density=90
|
||||||
Friction=15
|
Friction=15
|
||||||
Placement=80
|
Placement=80
|
||||||
TextureOverlay=brick
|
TextureOverlay=brick
|
||||||
|
|
|
@ -21,9 +21,8 @@ global func IsMovementControl(int ctrl)
|
||||||
/** Control throws selected item */
|
/** Control throws selected item */
|
||||||
global func IsThrowControl(int ctrl)
|
global func IsThrowControl(int ctrl)
|
||||||
{
|
{
|
||||||
// left mouse button
|
// right mouse button
|
||||||
if(ctrl == CON_Throw
|
if(ctrl == CON_Throw)
|
||||||
|| ctrl == CON_ThrowDelayed)
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -99,4 +98,4 @@ global func IsUseControl(int ctrl)
|
||||||
{
|
{
|
||||||
if (ctrl == CON_Use || ctrl == CON_UseAlt) return true;
|
if (ctrl == CON_Use || ctrl == CON_UseAlt) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,15 @@ global func Find_Hostile(int plr)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Similar to Find_Hostile, but defaults to treating all players as hostile when plr = NO_OWNER.
|
||||||
|
*/
|
||||||
|
global func Find_AnimalHostile(int plr)
|
||||||
|
{
|
||||||
|
if (plr == NO_OWNER) return Find_Not(Find_Owner(NO_OWNER));
|
||||||
|
return Find_Or(Find_Owner(NO_OWNER), Find_Hostile(plr));
|
||||||
|
}
|
||||||
|
|
||||||
global func Find_Allied(int plr)
|
global func Find_Allied(int plr)
|
||||||
{
|
{
|
||||||
var p = [C4FO_Or];
|
var p = [C4FO_Or];
|
||||||
|
|
|
@ -18,12 +18,11 @@ global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int stren
|
||||||
{
|
{
|
||||||
var release = status == CONS_Up;
|
var release = status == CONS_Up;
|
||||||
//Log("%d, %s, %i, %d, %d, %d, %v, %v", plr, GetPlayerControlName(ctrl), spec_id, x,y,strength, repeat, status);
|
//Log("%d, %s, %i, %d, %d, %d, %v, %v", plr, GetPlayerControlName(ctrl), spec_id, x,y,strength, repeat, status);
|
||||||
if (status == CONS_Moved) return false;
|
|
||||||
// Control handled by definition? Forward
|
// Control handled by definition? Forward
|
||||||
if (spec_id) return spec_id->ForwardedPlayerControl(plr, ctrl, x, y, strength, repeat, release);
|
if (spec_id) return spec_id->ForwardedPlayerControl(plr, ctrl, x, y, strength, repeat, status);
|
||||||
|
|
||||||
// Forward control to player
|
// Forward control to player
|
||||||
if (Control2Player(plr,ctrl, x, y, strength, repeat, release)) return true;
|
if (Control2Player(plr,ctrl, x, y, strength, repeat, status)) return true;
|
||||||
|
|
||||||
// Forward control to cursor
|
// Forward control to cursor
|
||||||
var cursor = GetCursor(plr);
|
var cursor = GetCursor(plr);
|
||||||
|
@ -34,7 +33,7 @@ global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int stren
|
||||||
|
|
||||||
// menu controls:
|
// menu controls:
|
||||||
|
|
||||||
if (cursor->~GetMenu())
|
if (cursor->~GetMenu() && status != CONS_Moved)
|
||||||
{
|
{
|
||||||
// direction keys are always forwarded to the menu
|
// direction keys are always forwarded to the menu
|
||||||
// (because the clonk shall not move while the menu is open)
|
// (because the clonk shall not move while the menu is open)
|
||||||
|
@ -83,11 +82,11 @@ global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int stren
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overload by effect?
|
// Overload by effect?
|
||||||
if (cursor->Control2Effect(plr, ctrl, cursorX, cursorY, strength, repeat, release)) return true;
|
if (cursor->Control2Effect(plr, ctrl, cursorX, cursorY, strength, repeat, status)) return true;
|
||||||
|
|
||||||
if (cursor->ObjectControl(plr, ctrl, cursorX, cursorY, strength, repeat, release))
|
if (cursor->ObjectControl(plr, ctrl, cursorX, cursorY, strength, repeat, status))
|
||||||
{
|
{
|
||||||
if (cursor && !release && !repeat)
|
if (cursor && status == CONS_Down && !repeat)
|
||||||
{
|
{
|
||||||
// non-mouse controls reset view
|
// non-mouse controls reset view
|
||||||
if (!x && !y) ResetCursorView(plr);
|
if (!x && !y) ResetCursorView(plr);
|
||||||
|
@ -127,7 +126,7 @@ global func PlayerHasVirtualCursor(int plr)
|
||||||
|
|
||||||
// Control2Player
|
// Control2Player
|
||||||
// Player-wide controls
|
// Player-wide controls
|
||||||
global func Control2Player(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
global func Control2Player(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
// select previous or next
|
// select previous or next
|
||||||
if (ctrl == CON_PreviousCrew)
|
if (ctrl == CON_PreviousCrew)
|
||||||
|
@ -202,7 +201,7 @@ global func StopSelected(int plr)
|
||||||
|
|
||||||
// Control2Effect
|
// Control2Effect
|
||||||
// Call control function in all effects that have "Control" in their name
|
// Call control function in all effects that have "Control" in their name
|
||||||
global func Control2Effect(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
global func Control2Effect(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
// x and y are local coordinates
|
// x and y are local coordinates
|
||||||
if (!this) return false;
|
if (!this) return false;
|
||||||
|
@ -213,7 +212,7 @@ global func Control2Effect(int plr, int ctrl, int x, int y, int strength, bool r
|
||||||
{
|
{
|
||||||
iEffect = GetEffect("*Control*", this, i);
|
iEffect = GetEffect("*Control*", this, i);
|
||||||
if (iEffect)
|
if (iEffect)
|
||||||
if (EffectCall(this, iEffect, "Control", ctrl, x,y,strength, repeat, release))
|
if (EffectCall(this, iEffect, "Control", ctrl, x,y,strength, repeat, status))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// No effect handled the control
|
// No effect handled the control
|
||||||
|
@ -224,7 +223,7 @@ global func Control2Effect(int plr, int ctrl, int x, int y, int strength, bool r
|
||||||
// Called from PlayerControl when a control is issued to the cursor
|
// Called from PlayerControl when a control is issued to the cursor
|
||||||
// Return whether handled
|
// Return whether handled
|
||||||
// To be overloaded by specific objects to enable additional controls
|
// To be overloaded by specific objects to enable additional controls
|
||||||
global func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
global func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
if (!this) return false;
|
if (!this) return false;
|
||||||
|
|
||||||
|
@ -233,7 +232,7 @@ global func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
|
|
||||||
// Movement controls
|
// Movement controls
|
||||||
if (ctrl == CON_Left || ctrl == CON_Right || ctrl == CON_Up || ctrl == CON_Down || ctrl == CON_Jump)
|
if (ctrl == CON_Left || ctrl == CON_Right || ctrl == CON_Up || ctrl == CON_Down || ctrl == CON_Jump)
|
||||||
return ObjectControlMovement(plr, ctrl, strength, release, repeat);
|
return ObjectControlMovement(plr, ctrl, strength, status, repeat);
|
||||||
|
|
||||||
// Unhandled control
|
// Unhandled control
|
||||||
return false;
|
return false;
|
||||||
|
@ -276,7 +275,7 @@ global func NameComDir(comdir)
|
||||||
}
|
}
|
||||||
// Called when CON_Left/Right/Up/Down controls are issued/released
|
// Called when CON_Left/Right/Up/Down controls are issued/released
|
||||||
// Return whether handled
|
// Return whether handled
|
||||||
global func ObjectControlMovement(int plr, int ctrl, int strength, bool release, bool repeat)
|
global func ObjectControlMovement(int plr, int ctrl, int strength, int status, bool repeat)
|
||||||
{
|
{
|
||||||
if (!this) return false;
|
if (!this) return false;
|
||||||
|
|
||||||
|
@ -284,13 +283,13 @@ global func ObjectControlMovement(int plr, int ctrl, int strength, bool release,
|
||||||
if (Contained()) return false;
|
if (Contained()) return false;
|
||||||
|
|
||||||
// this is for controlling movement with Analogpad
|
// this is for controlling movement with Analogpad
|
||||||
if(!release)
|
if(status == CONS_Down)
|
||||||
if(strength != nil && strength < CON_Gamepad_Deadzone)
|
if(strength != nil && strength < CON_Gamepad_Deadzone)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var proc = GetProcedure();
|
var proc = GetProcedure();
|
||||||
// Some specific movement controls
|
// Some specific movement controls
|
||||||
if (!release)
|
if (status == CONS_Down)
|
||||||
{
|
{
|
||||||
// Jump control
|
// Jump control
|
||||||
if (ctrl == CON_Jump)
|
if (ctrl == CON_Jump)
|
||||||
|
|
|
@ -37,8 +37,6 @@
|
||||||
#
|
#
|
||||||
# Gamepad controls
|
# Gamepad controls
|
||||||
# -------------------------------------
|
# -------------------------------------
|
||||||
# ThrowDelayed
|
|
||||||
# UseDelayed
|
|
||||||
# AimUp AimDown AimLeft AimRight
|
# AimUp AimDown AimLeft AimRight
|
||||||
# AimAxisUp AimAxisDown AimAxisLeft AimAxisRight
|
# AimAxisUp AimAxisDown AimAxisLeft AimAxisRight
|
||||||
#
|
#
|
||||||
|
@ -59,26 +57,6 @@
|
||||||
DefaultDisabled=1
|
DefaultDisabled=1
|
||||||
CoordinateSpace=Viewport
|
CoordinateSpace=Viewport
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=AimUp
|
|
||||||
DefaultDisabled=1
|
|
||||||
Hold=1
|
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=AimDown
|
|
||||||
DefaultDisabled=1
|
|
||||||
Hold=1
|
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=AimLeft
|
|
||||||
DefaultDisabled=1
|
|
||||||
Hold=1
|
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=AimRight
|
|
||||||
DefaultDisabled=1
|
|
||||||
Hold=1
|
|
||||||
|
|
||||||
[ControlDef]
|
[ControlDef]
|
||||||
Identifier=AimAxisUp
|
Identifier=AimAxisUp
|
||||||
GUIName=$CON_AimAxisUp$
|
GUIName=$CON_AimAxisUp$
|
||||||
|
@ -164,12 +142,6 @@
|
||||||
Hold=1
|
Hold=1
|
||||||
SendCursorPos=1
|
SendCursorPos=1
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=ThrowDelayed
|
|
||||||
GUIName=$CON_Throw$
|
|
||||||
GUIDesc=$CON_Throw_Desc$
|
|
||||||
Hold=1
|
|
||||||
|
|
||||||
[ControlDef]
|
[ControlDef]
|
||||||
Identifier=Drop
|
Identifier=Drop
|
||||||
GUIName=$CON_Drop$
|
GUIName=$CON_Drop$
|
||||||
|
@ -286,13 +258,6 @@
|
||||||
Hold=1
|
Hold=1
|
||||||
SendCursorPos=1
|
SendCursorPos=1
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=UseDelayed
|
|
||||||
GUIName=$CON_Use$
|
|
||||||
GUIDesc=$CON_Use_Desc$
|
|
||||||
Hold=1
|
|
||||||
SendCursorPos=1
|
|
||||||
|
|
||||||
[ControlDef]
|
[ControlDef]
|
||||||
Identifier=UseAlt
|
Identifier=UseAlt
|
||||||
GUIName=$CON_UseAlt$
|
GUIName=$CON_UseAlt$
|
||||||
|
@ -300,13 +265,6 @@
|
||||||
Hold=1
|
Hold=1
|
||||||
SendCursorPos=1
|
SendCursorPos=1
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=UseAltDelayed
|
|
||||||
GUIName=$CON_UseAlt$
|
|
||||||
GUIDesc=$CON_UseAlt_Desc$
|
|
||||||
Hold=1
|
|
||||||
SendCursorPos=1
|
|
||||||
|
|
||||||
[ControlDef]
|
[ControlDef]
|
||||||
Identifier=CancelUse
|
Identifier=CancelUse
|
||||||
|
|
||||||
|
@ -960,11 +918,54 @@
|
||||||
GUIGroup=40
|
GUIGroup=40
|
||||||
Control=Interact
|
Control=Interact
|
||||||
|
|
||||||
|
[Assignment]
|
||||||
|
Key=CON_Interact,CON_Left
|
||||||
|
Control=InteractNext_Left
|
||||||
|
Priority=75
|
||||||
|
|
||||||
|
[Assignment]
|
||||||
|
Key=CON_Interact,CON_Right
|
||||||
|
Control=InteractNext_Right
|
||||||
|
Priority=75
|
||||||
|
|
||||||
|
[Assignment]
|
||||||
|
Key=CON_Interact,CON_Up
|
||||||
|
Control=InteractNext_CycleObject
|
||||||
|
Priority=75
|
||||||
|
|
||||||
|
[Assignment]
|
||||||
|
Key=CON_Interact,CON_Down
|
||||||
|
Control=InteractNext_Stop
|
||||||
|
Priority=75
|
||||||
|
|
||||||
[Assignment]
|
[Assignment]
|
||||||
Key=ControllerButtonX
|
Key=ControllerButtonX
|
||||||
Control=PickUp
|
Control=PickUp
|
||||||
GUIGroup=50
|
GUIGroup=50
|
||||||
|
|
||||||
|
[Assignment]
|
||||||
|
Key=CON_PickUp,CON_Left
|
||||||
|
Control=PickUpNext_Left
|
||||||
|
|
||||||
|
[Assignment]
|
||||||
|
Key=CON_PickUp,CON_Right
|
||||||
|
Control=PickUpNext_Right
|
||||||
|
|
||||||
|
[Assignment]
|
||||||
|
Key=CON_PickUp,CON_Up
|
||||||
|
Control=PickUpNext_All
|
||||||
|
Priority=75
|
||||||
|
|
||||||
|
[Assignment]
|
||||||
|
Key=CON_PickUp,CON_Down
|
||||||
|
Control=PickUpNext_Stop
|
||||||
|
Priority=75
|
||||||
|
|
||||||
|
[Assignment]
|
||||||
|
Key=CON_PickUp,CON_Throw
|
||||||
|
Control=Drop
|
||||||
|
Priority=75
|
||||||
|
|
||||||
# Crew
|
# Crew
|
||||||
|
|
||||||
[Assignment]
|
[Assignment]
|
||||||
|
@ -985,13 +986,13 @@
|
||||||
GUIDesc=$KEY_GamepadUse_Desc$
|
GUIDesc=$KEY_GamepadUse_Desc$
|
||||||
GUIGroup=20
|
GUIGroup=20
|
||||||
Priority=100
|
Priority=100
|
||||||
Control=UseDelayed
|
Control=Use
|
||||||
|
|
||||||
[Assignment]
|
[Assignment]
|
||||||
Key=ControllerLeftTrigger
|
Key=ControllerLeftTrigger
|
||||||
GUIGroup=20
|
GUIGroup=20
|
||||||
Priority=100
|
Priority=100
|
||||||
Control=ThrowDelayed
|
Control=Throw
|
||||||
|
|
||||||
# TODO: Zoom
|
# TODO: Zoom
|
||||||
|
|
||||||
|
@ -1017,58 +1018,12 @@
|
||||||
Name=*_GamepadCon_*
|
Name=*_GamepadCon_*
|
||||||
|
|
||||||
[Assignment]
|
[Assignment]
|
||||||
Key=CON_AimAxisLeft
|
Key=CON_Down,CON_Throw
|
||||||
Priority=50
|
|
||||||
Control=Left
|
|
||||||
|
|
||||||
[Assignment]
|
|
||||||
Key=CON_AimAxisRight
|
|
||||||
Priority=50
|
|
||||||
Control=Right
|
|
||||||
|
|
||||||
[Assignment]
|
|
||||||
Key=CON_AimAxisDown
|
|
||||||
Priority=50
|
|
||||||
Control=Down
|
|
||||||
|
|
||||||
[Assignment]
|
|
||||||
Key=CON_AimAxisUp
|
|
||||||
Priority=50
|
|
||||||
Control=Up
|
|
||||||
|
|
||||||
[Assignment]
|
|
||||||
Key=CON_Left
|
|
||||||
Priority=70
|
|
||||||
Control=AimLeft
|
|
||||||
|
|
||||||
[Assignment]
|
|
||||||
Key=CON_Right
|
|
||||||
Priority=70
|
|
||||||
Control=AimRight
|
|
||||||
|
|
||||||
[Assignment]
|
|
||||||
Key=CON_Down
|
|
||||||
Priority=70
|
|
||||||
Control=AimDown
|
|
||||||
|
|
||||||
[Assignment]
|
|
||||||
Key=CON_Up
|
|
||||||
Priority=70
|
|
||||||
Control=AimUp
|
|
||||||
|
|
||||||
[Assignment]
|
|
||||||
Key=CON_Down,CON_UseDelayed
|
|
||||||
GUIDisabled=1
|
GUIDisabled=1
|
||||||
GUIGroup=20
|
GUIGroup=20
|
||||||
Priority=150
|
Priority=150
|
||||||
Control=Drop
|
Control=Drop
|
||||||
|
|
||||||
[Assignment]
|
|
||||||
Key=CON_UseDelayed
|
|
||||||
GUIName=None
|
|
||||||
Priority=50
|
|
||||||
Control=ThrowDelayed
|
|
||||||
|
|
||||||
# ======================================================================= #
|
# ======================================================================= #
|
||||||
# Default mouse control #
|
# Default mouse control #
|
||||||
# ======================================================================= #
|
# ======================================================================= #
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
#appendto Library_ClonkControl
|
#appendto Library_ClonkControl
|
||||||
|
|
||||||
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
if (!this)
|
if (!this)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Spawn menu
|
// Spawn menu
|
||||||
if (ctrl == CON_SpawnMenu && !release)
|
if (ctrl == CON_SpawnMenu && status == CONS_Down)
|
||||||
{
|
{
|
||||||
// Close any menu if open.
|
// Close any menu if open.
|
||||||
if (GetMenu())
|
if (GetMenu())
|
||||||
|
@ -31,5 +31,5 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unhandled control will be handled by the library itself.
|
// Unhandled control will be handled by the library itself.
|
||||||
return _inherited(plr, ctrl, x, y, strength, repeat, release, ...);
|
return _inherited(plr, ctrl, x, y, strength, repeat, status, ...);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// Shows and hides the tutorial guide if the [H] button is pressed.
|
// Shows and hides the tutorial guide if the [H] button is pressed.
|
||||||
|
|
||||||
global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int strength, bool repeat, bool release)
|
global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int strength, bool repeat, int status)
|
||||||
{
|
{
|
||||||
if (ctrl != CON_TutorialGuide)
|
if (ctrl != CON_TutorialGuide)
|
||||||
return _inherited(plr, ctrl, spec_id, x, y, strength, repeat, release, ...);
|
return _inherited(plr, ctrl, spec_id, x, y, strength, repeat, status, ...);
|
||||||
// Don't do anything if the player is a sequence.
|
// Don't do anything if the player is a sequence.
|
||||||
if (GetActiveSequence())
|
if (GetActiveSequence())
|
||||||
return;
|
return;
|
||||||
|
@ -17,4 +17,4 @@ global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int stren
|
||||||
else
|
else
|
||||||
guide->HideGuide();
|
guide->HideGuide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
Icon=34
|
Icon=34
|
||||||
Title=AcidRift
|
Title=AcidRift
|
||||||
Version=6,0
|
Version=6,0
|
||||||
Difficulty=70
|
Difficulty=80
|
||||||
|
|
||||||
[Definitions]
|
[Definitions]
|
||||||
Definition1=Objects.ocd
|
Definition1=Objects.ocd
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
Icon=36
|
Icon=36
|
||||||
Title=Chine
|
Title=Chine
|
||||||
Version=6,0
|
Version=6,0
|
||||||
Difficulty=50
|
Difficulty=60
|
||||||
|
|
||||||
[Definitions]
|
[Definitions]
|
||||||
Definition1=Objects.ocd
|
Definition1=Objects.ocd
|
||||||
|
|
|
@ -2,7 +2,7 @@ Flooded Veins
|
||||||
|
|
||||||
You stumble upon an abandoned settlement beneath the Forest of Orgos in your quest for more gold. Legends tell a story of even more valuable materials named gems which may be found here. Might this abandoned settlement be a failed attempt to find these gems? Set up an expedition to explore the flooded caves around and to discover possible gem veins.
|
You stumble upon an abandoned settlement beneath the Forest of Orgos in your quest for more gold. Legends tell a story of even more valuable materials named gems which may be found here. Might this abandoned settlement be a failed attempt to find these gems? Set up an expedition to explore the flooded caves around and to discover possible gem veins.
|
||||||
|
|
||||||
Goal: Sell gems
|
Goal: Sell gems.
|
||||||
|
|
||||||
Hints:
|
Hints:
|
||||||
- The flooded caves may be drained using pumps, you can get rid off the excess water where you entered the cave.
|
- The flooded caves may be drained using pumps, you can get rid off the excess water where you entered the cave.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
Title=GemGrabbers
|
Title=GemGrabbers
|
||||||
Icon=35
|
Icon=35
|
||||||
Version=6,0
|
Version=6,0
|
||||||
Difficulty=80
|
Difficulty=90
|
||||||
|
|
||||||
[Definitions]
|
[Definitions]
|
||||||
Definition1=Objects.ocd
|
Definition1=Objects.ocd
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
Icon=23
|
Icon=23
|
||||||
Title=Krakatoa
|
Title=Krakatoa
|
||||||
Version=6,0
|
Version=6,0
|
||||||
Difficulty=60
|
Difficulty=70
|
||||||
|
|
||||||
[Definitions]
|
[Definitions]
|
||||||
Definition1=Objects.ocd
|
Definition1=Objects.ocd
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
Rasches Raffinieren
|
||||||
|
|
||||||
|
An apparently infinite oil well is hidden deep inside a cave. Connect the well to the refinery drain outside of the cave using pumps and supply the refinery.
|
||||||
|
|
||||||
|
Ziel: Pumpe Öl.
|
||||||
|
|
||||||
|
Tipps:
|
||||||
|
- Do not set oil on fire, it will burn for a long time.
|
||||||
|
- You can connect multiple pipes to the refinery drain.
|
|
@ -0,0 +1,9 @@
|
||||||
|
Rapid Refining
|
||||||
|
|
||||||
|
An apparently infinite oil well is hidden deep inside a cave. Connect the well to the refinery drain outside of the cave using pumps and supply the refinery.
|
||||||
|
|
||||||
|
Goal: Pump oil.
|
||||||
|
|
||||||
|
Hints:
|
||||||
|
- Do not set oil on fire, it will burn for a long time.
|
||||||
|
- You can connect multiple pipes to the refinery drain.
|
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
|
@ -0,0 +1,250 @@
|
||||||
|
/**
|
||||||
|
Rapid Refining
|
||||||
|
Use the oil from an underground well to power your settlement.
|
||||||
|
|
||||||
|
@author Maikel
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include Library_Map
|
||||||
|
|
||||||
|
|
||||||
|
// Called be the engine: draw the complete map here.
|
||||||
|
protected func InitializeMap(proplist map)
|
||||||
|
{
|
||||||
|
// Map settings.
|
||||||
|
var overground_wdt = 40;
|
||||||
|
var overground_hgt = 20;
|
||||||
|
|
||||||
|
// Retrieve the settings according to the MapSize setting.
|
||||||
|
var map_size;
|
||||||
|
if (SCENPAR_MapSize == 1)
|
||||||
|
map_size = [250, 150];
|
||||||
|
if (SCENPAR_MapSize == 2)
|
||||||
|
map_size = [275, 150];
|
||||||
|
if (SCENPAR_MapSize == 3)
|
||||||
|
map_size = [300, 150];
|
||||||
|
|
||||||
|
// Set the map size.
|
||||||
|
map->Resize(map_size[0], map_size[1]);
|
||||||
|
|
||||||
|
// The overground area is in the top left corner, the underground are thereby the remainder.
|
||||||
|
var underground = {Algo = MAPALGO_Not, Op = {Algo = MAPALGO_Rect, X = 0, Y = 0, Wdt = overground_wdt, Hgt = overground_hgt}};
|
||||||
|
Draw("Earth", underground);
|
||||||
|
|
||||||
|
// Draw materials in the underground area and then overlay the rest of the map.
|
||||||
|
DrawMaterial("Earth-earth_root", underground, 2, 12);
|
||||||
|
DrawMaterial("Earth-earth_spongy", underground, 2, 12);
|
||||||
|
DrawMaterial("Granite", underground, 3, 6);
|
||||||
|
DrawMaterial("Tunnel", underground, 5, 8);
|
||||||
|
DrawMaterial("Rock-rock", underground, 3, 4);
|
||||||
|
DrawMaterial("Rock", underground, 3, 4);
|
||||||
|
DrawMaterial("Ore", underground, 6, 6);
|
||||||
|
DrawMaterial("Firestone", underground, 5, 4);
|
||||||
|
DrawMaterial("Coal", underground, 6, 4);
|
||||||
|
|
||||||
|
// Draw some underground water lakes.
|
||||||
|
var underground_water = {Algo = MAPALGO_And, Op = [underground, {Algo = MAPALGO_Rect, X = 0, Y = map.Hgt / 2, Wdt = map.Wdt - 20, Hgt = map.Hgt / 2}]};
|
||||||
|
DrawMaterial("Water", underground_water, [4, 10], 6);
|
||||||
|
|
||||||
|
// The entrance border is out of granite.
|
||||||
|
var entrance_border = {Algo = MAPALGO_Border, Left = 3, Op = underground};
|
||||||
|
entrance_border = {Algo = MAPALGO_Or, Op = [entrance_border, {Algo = MAPALGO_Turbulence, Iterations = 2, Amplitude = [6, 8], Scale = [6, 8], Seed = Random(65536), Op = entrance_border}]};
|
||||||
|
DrawRock(entrance_border);
|
||||||
|
|
||||||
|
// The entrance floor is out of earth and brick.
|
||||||
|
var entrance_floor = {Algo = MAPALGO_Border, Top = 3, Op = underground};
|
||||||
|
Draw("Brick", entrance_floor);
|
||||||
|
var entrance_floor_earth = {Algo = MAPALGO_Border, Top = 2, Op = underground};
|
||||||
|
var entrance_floor_earth = {Algo = MAPALGO_And, Op = [entrance_floor_earth, {Algo = MAPALGO_Rect, X = 4, Y = 0, Wdt = 17, Hgt = map.Hgt}]};
|
||||||
|
Draw("Earth", entrance_floor_earth);
|
||||||
|
|
||||||
|
// There are borders on the full underground area of the map.
|
||||||
|
var wdt = 3;
|
||||||
|
var underground_border = {Algo = MAPALGO_Not, Op = {Algo = MAPALGO_Rect, X = wdt, Y = wdt, Wdt = map.Wdt - 2 * wdt, Hgt = map.Hgt - 2 * wdt}};
|
||||||
|
underground_border = {Algo = MAPALGO_And, Op = [underground_border, underground]};
|
||||||
|
underground_border = {Algo = MAPALGO_Or, Op = [underground_border, {Algo = MAPALGO_Turbulence, Iterations = 6, Amplitude = 12, Scale = 16, Seed = Random(65536), Op = underground_border}]};
|
||||||
|
underground_border = {Algo = MAPALGO_And, Op = [underground_border, underground, {Algo = MAPALGO_Not, Op = entrance_floor}]};
|
||||||
|
DrawRock(underground_border);
|
||||||
|
|
||||||
|
// Draw a tunnel to the oil well.
|
||||||
|
DrawMainTunnel(map, overground_wdt, overground_hgt);
|
||||||
|
|
||||||
|
// Some slabs of granite/rock which block the path to the oil.
|
||||||
|
DrawRockSlabs(map);
|
||||||
|
|
||||||
|
// There is a smaller oil field below the entrance.
|
||||||
|
DrawOilLakes(map);
|
||||||
|
|
||||||
|
// The main oil well is in the bottom right of the map.
|
||||||
|
DrawOilWell(map, underground_border);
|
||||||
|
|
||||||
|
// A large water lake at the bottom of the map.
|
||||||
|
DrawWaterLake(map, underground_border);
|
||||||
|
|
||||||
|
// Some liquid veins above the oil well.
|
||||||
|
DrawLiquidVeins(map, underground_border);
|
||||||
|
|
||||||
|
// Fix liquid borders.
|
||||||
|
FixLiquidBorders();
|
||||||
|
|
||||||
|
// Return true to tell the engine a map has been successfully created.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func DrawMainTunnel(proplist map, int overground_wdt, int overground_hgt)
|
||||||
|
{
|
||||||
|
var sx = overground_wdt;
|
||||||
|
var sy = overground_hgt - 3;
|
||||||
|
var ex = map.Wdt - 20;
|
||||||
|
var ey = map.Hgt - 30;
|
||||||
|
var nr_steps = 10;
|
||||||
|
var tunnel_x = [], tunnel_y = [];
|
||||||
|
for (var index = 0; index <= nr_steps; index++)
|
||||||
|
{
|
||||||
|
var dev = 4 * Min(index, nr_steps - index);
|
||||||
|
tunnel_x[index] = sx + (ex - sx) * index / nr_steps + RandomX(-dev, dev);
|
||||||
|
tunnel_y[index] = sy + (ey - sy) * index / nr_steps + RandomX(-dev, dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw main tunnel.
|
||||||
|
var tunnel = {Algo = MAPALGO_Polygon, X = tunnel_x, Y = tunnel_y, Wdt = 3, Empty = true, Open = true};
|
||||||
|
tunnel = {Algo = MAPALGO_Or, Op = [tunnel, {Algo = MAPALGO_Turbulence, Iterations = 2, Amplitude = [6, 8], Scale = [6, 8], Seed = Random(65536), Op = tunnel}]};
|
||||||
|
Draw("Tunnel", tunnel);
|
||||||
|
|
||||||
|
// Draw branches.
|
||||||
|
for (var index = 2; index <= nr_steps - 2; index++)
|
||||||
|
{
|
||||||
|
var x = tunnel_x[index];
|
||||||
|
var y = tunnel_y[index];
|
||||||
|
var to_x = x + RandomX(-5, 5);
|
||||||
|
var to_y = y + (2 * Random(2) - 1) * RandomX(16, 22);
|
||||||
|
var tunnel_branch = {Algo = MAPALGO_Polygon, X = [x, to_x], Y = [y, to_y], Wdt = 2, Empty = true, Open = true};
|
||||||
|
tunnel_branch = {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = 12, Scale = 8, Seed = Random(65536), Op = tunnel_branch};
|
||||||
|
Draw("Tunnel", tunnel_branch);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func DrawRockSlabs(proplist map)
|
||||||
|
{
|
||||||
|
var slabs = {Algo = MAPALGO_Lines, X = 6, Y = 1, Distance = 32};
|
||||||
|
slabs = {Algo = MAPALGO_And, Op = [slabs, {Algo = MAPALGO_RndChecker, Ratio = 75, Seed = Random(65536)}]};
|
||||||
|
slabs = {Algo = MAPALGO_Turbulence, Iterations = 2, Amplitude = [6, 8], Scale = [6, 8], Seed = Random(65536), Op = slabs};
|
||||||
|
slabs = {Algo = MAPALGO_And, Op = [slabs, {Algo = MAPALGO_Rect, X = map.Wdt / 3, Y = 0, Wdt = 2 * map.Wdt / 3, Hgt = map.Hgt}]};
|
||||||
|
DrawRock(slabs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func DrawWaterLake(proplist map, proplist underground_border)
|
||||||
|
{
|
||||||
|
var lake_height = 20;
|
||||||
|
var lake_width = 80;
|
||||||
|
var waterfall_height = 62;
|
||||||
|
var tunnel_height = 6;
|
||||||
|
|
||||||
|
// Draw a large lake with tunnel above.
|
||||||
|
underground_border = {Algo = MAPALGO_And, Op = [underground_border, {Algo = MAPALGO_Not, Op = {Algo = MAPALGO_Rect, X = 0, Y = map.Hgt - lake_height - 2, Wdt = lake_width, Hgt = 6}}]};
|
||||||
|
var lake_floor_rock = {Algo = MAPALGO_And, Op = [{Algo = MAPALGO_Lines, X = 3, Y = 0, Distance = 10}, {Algo = MAPALGO_Rect, X = 0, Y = map.Hgt - 7, Wdt = lake_width, Hgt = 7}]};
|
||||||
|
var lake_floor_rock = {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = 16, Scale = 8, Seed = Random(65536), Op = lake_floor_rock};
|
||||||
|
underground_border = {Algo = MAPALGO_Or, Op = [underground_border, lake_floor_rock]};
|
||||||
|
DrawRock(lake_floor_rock);
|
||||||
|
|
||||||
|
|
||||||
|
var tunnel = {Algo = MAPALGO_Rect, X = 0, Y = map.Hgt - lake_height - tunnel_height, Wdt = lake_width, Hgt = tunnel_height};
|
||||||
|
tunnel = {Algo = MAPALGO_Or, Op = [tunnel, {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = 16, Scale = 8, Seed = Random(65536), Op = tunnel}]};
|
||||||
|
tunnel = {Algo = MAPALGO_And, Op = [tunnel, {Algo = MAPALGO_Not, Op = underground_border}]};
|
||||||
|
Draw("Tunnel", tunnel);
|
||||||
|
|
||||||
|
var lake = {Algo = MAPALGO_Rect, X = 0, Y = map.Hgt - lake_height, Wdt = lake_width, Hgt = lake_height};
|
||||||
|
lake = {Algo = MAPALGO_And, Op = [lake, {Algo = MAPALGO_Not, Op = underground_border}]};
|
||||||
|
Draw("Water:Water", lake);
|
||||||
|
|
||||||
|
var lake_floor = {Algo = MAPALGO_Border, Bottom = 2, Op = lake};
|
||||||
|
Draw("Sand", lake_floor);
|
||||||
|
|
||||||
|
var lake_boundary = {Algo = MAPALGO_Rect, X = lake_width - 1, Y = map.Hgt - lake_height, Wdt = 2, Hgt = lake_height};
|
||||||
|
lake_boundary = {Algo = MAPALGO_Or, Op = [lake_boundary, {Algo = MAPALGO_Turbulence, Iterations = 3, Amplitude = 12, Scale = 12, Seed = Random(65536), Op = lake_boundary}]};
|
||||||
|
Draw("Everrock", lake_boundary);
|
||||||
|
var lake_boundary_rock = {Algo = MAPALGO_Border, Wdt = -2, Op = lake_boundary};
|
||||||
|
DrawRock(lake_boundary_rock);
|
||||||
|
|
||||||
|
// Draw a waterfall pooring into the lake.
|
||||||
|
var waterfall = {Algo = MAPALGO_Rect, X = 3, Y = map.Hgt - lake_height - waterfall_height, Wdt = 9, Hgt = waterfall_height};
|
||||||
|
waterfall = {Algo = MAPALGO_Or, Op = [waterfall, {Algo = MAPALGO_Turbulence, Iterations = 3, Amplitude = 12, Scale = 12, Seed = Random(65536), Op = waterfall}]};
|
||||||
|
waterfall = {Algo = MAPALGO_And, Op = [waterfall, {Algo = MAPALGO_Not, Op = underground_border}, {Algo = MAPALGO_Not, Op = lake}]};
|
||||||
|
Draw("Tunnel", waterfall);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func DrawOilLakes(proplist map)
|
||||||
|
{
|
||||||
|
for (var cnt = 0; cnt < 3; cnt++)
|
||||||
|
{
|
||||||
|
var oil_lake_x = RandomX(map.Wdt / 10, 3 * map.Wdt / 10);
|
||||||
|
var oil_lake_y = RandomX(2 * map.Hgt / 7, 5 * map.Hgt / 7);
|
||||||
|
var oil_lake = {Algo = MAPALGO_Rect, X = oil_lake_x, Y = oil_lake_y, Wdt = 13, Hgt = 15};
|
||||||
|
oil_lake = {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = 10, Scale = 10, Seed = Random(65536), Op = oil_lake};
|
||||||
|
var oil_lake_filled = {Algo = MAPALGO_And, Op = [oil_lake, {Algo = MAPALGO_Rect, X = 0, Y = oil_lake_y - 3, Wdt = map.Wdt, Hgt = map.Hgt}]};
|
||||||
|
Draw("Tunnel", oil_lake);
|
||||||
|
Draw("Oil", oil_lake_filled);
|
||||||
|
var oil_lake_border = {Algo = MAPALGO_Border, Left = 2, Right = 2, Bottom = 3, Top = 1, Op = oil_lake};
|
||||||
|
DrawRock(oil_lake_border);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func DrawOilWell(proplist map, proplist underground_border)
|
||||||
|
{
|
||||||
|
var oil_field = {Algo = MAPALGO_Polygon,
|
||||||
|
X = [map.Wdt, map.Wdt - 16, map.Wdt - 14, map.Wdt - 10, map.Wdt - 17, map.Wdt - 22, map.Wdt - 22, map.Wdt - 27, map.Wdt - 29],
|
||||||
|
Y = [map.Hgt - 5, map.Hgt - 5, map.Hgt - 12, map.Hgt - 18, map.Hgt - 23, map.Hgt - 20, map.Hgt - 12, map.Hgt - 12, map.Hgt - 16],
|
||||||
|
Wdt = 3, Empty = true, Open = true};
|
||||||
|
var oil_field_oil = {Algo = MAPALGO_And, Op = [oil_field, {Algo = MAPALGO_Rect, X = 0, Y = map.Hgt - 8, Wdt = map.Wdt, Hgt = 8}]};
|
||||||
|
var oil_field_water = {Algo = MAPALGO_And, Op = [oil_field, {Algo = MAPALGO_Rect, X = 0, Y = 0, Wdt = map.Wdt, Hgt = map.Hgt - 8}]};
|
||||||
|
Draw("Oil:Oil", oil_field_oil);
|
||||||
|
Draw("Water", oil_field_water);
|
||||||
|
var oil_field_border = {Algo = MAPALGO_Border, Left = -3, Right = -3, Top = -3, Bottom = -5, Op = oil_field};
|
||||||
|
Draw("Everrock", oil_field_border);
|
||||||
|
var oil_field_entrance = {Algo = MAPALGO_Rect, X = map.Wdt - 31, Y = map.Hgt - 22, Wdt = 5, Hgt = 5};
|
||||||
|
Draw("Tunnel", oil_field_entrance);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func DrawLiquidVeins(proplist map, proplist underground_border)
|
||||||
|
{
|
||||||
|
// Draw some gold as a source of wealth.
|
||||||
|
var gold = {Algo = MAPALGO_Rect, X = map.Wdt - 60, Y = 10, Wdt = 50, Hgt = 36};
|
||||||
|
gold = {Algo = MAPALGO_And, Op = [gold, {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = 12, Scale = 12, Seed = Random(65536), Op = gold}]};
|
||||||
|
DrawMaterial("Gold", gold, 4, 30);
|
||||||
|
|
||||||
|
// Draw the veins.
|
||||||
|
var vein_material = "Water";
|
||||||
|
if (SCENPAR_Difficulty == 2)
|
||||||
|
vein_material = "Acid";
|
||||||
|
if (SCENPAR_Difficulty == 3)
|
||||||
|
vein_material = "DuroLava";
|
||||||
|
var vein_area = {Algo = MAPALGO_Polygon, X = [map.Wdt - 96, map.Wdt, map.Wdt, map.Wdt - 44], Y = [0, 0, 108, 82]};
|
||||||
|
vein_area = {Algo = MAPALGO_And, Op = [vein_area, {Algo = MAPALGO_Not, Op = underground_border}]};
|
||||||
|
|
||||||
|
var veins = {Algo = MAPALGO_Or, Op = [
|
||||||
|
{Algo = MAPALGO_Lines, X = 2, Y = -1, Distance = 12},
|
||||||
|
{Algo = MAPALGO_Lines, X = 2, Y = 1, Distance = 12},
|
||||||
|
{Algo = MAPALGO_Lines, X = 0, Y = 1, Distance = 16}
|
||||||
|
]};
|
||||||
|
veins = {Algo = MAPALGO_And, Op = [veins, vein_area]};
|
||||||
|
veins = {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = 12, Scale = 12, Seed = Random(65536), Op = veins};
|
||||||
|
|
||||||
|
Draw(vein_material, veins);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Helper Functions --*/
|
||||||
|
|
||||||
|
public func DrawRock(proplist layer)
|
||||||
|
{
|
||||||
|
Draw("Granite", layer);
|
||||||
|
DrawMaterial("Rock-rock", layer, 4, 18);
|
||||||
|
DrawMaterial("Rock", layer, 4, 18);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
[ParameterDef]
|
||||||
|
Name=$Difficulty$
|
||||||
|
Description=$DescDifficulty$
|
||||||
|
ID=Difficulty
|
||||||
|
Default=1
|
||||||
|
LeagueValue=3
|
||||||
|
|
||||||
|
[Options]
|
||||||
|
|
||||||
|
[Option]
|
||||||
|
Name=$DiffNormal$
|
||||||
|
Description=$DescDiffNormal$
|
||||||
|
Value=1
|
||||||
|
|
||||||
|
[Option]
|
||||||
|
Name=$DiffHard$
|
||||||
|
Description=$DescDiffHard$
|
||||||
|
Value=2
|
||||||
|
|
||||||
|
[Option]
|
||||||
|
Name=$DiffInsane$
|
||||||
|
Description=$DescDiffInsane$
|
||||||
|
Value=3
|
||||||
|
|
||||||
|
[ParameterDef]
|
||||||
|
Name=$MapSize$
|
||||||
|
Description=$DescMapSize$
|
||||||
|
ID=MapSize
|
||||||
|
Default=1
|
||||||
|
LeagueValue=1
|
||||||
|
|
||||||
|
[Options]
|
||||||
|
|
||||||
|
[Option]
|
||||||
|
Name=$MapSmall$
|
||||||
|
Description=$DescMapSmall$
|
||||||
|
Value=1
|
||||||
|
|
||||||
|
[Option]
|
||||||
|
Name=$MapAverage$
|
||||||
|
Description=$DescMapAverage$
|
||||||
|
Value=2
|
||||||
|
|
||||||
|
[Option]
|
||||||
|
Name=$MapLarge$
|
||||||
|
Description=$DescMapLarge$
|
||||||
|
Value=3
|
|
@ -0,0 +1,14 @@
|
||||||
|
[DefCore]
|
||||||
|
id=RefineryDrain
|
||||||
|
Version=6,0
|
||||||
|
Category=C4D_Structure
|
||||||
|
Width=16
|
||||||
|
Height=32
|
||||||
|
Offset=-8,-16
|
||||||
|
Vertices=4
|
||||||
|
VertexX=-8,-8,8,8
|
||||||
|
VertexY=-2,15,-2,15
|
||||||
|
VertexCNAT=5,9,6,10
|
||||||
|
VertexFriction=50,50,100,100
|
||||||
|
Construction=1
|
||||||
|
Mass=10
|
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
|
@ -0,0 +1,99 @@
|
||||||
|
/**
|
||||||
|
Refinery Drain
|
||||||
|
Oil must be pumped into this structure to be processed further.
|
||||||
|
|
||||||
|
@author Maikel
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include Library_Structure
|
||||||
|
#include Library_Ownable
|
||||||
|
#include Library_Tank
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Pipeline --*/
|
||||||
|
|
||||||
|
public func GetLiquidContainerMaxFillLevel()
|
||||||
|
{
|
||||||
|
return 10**9;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func IsLiquidContainerForMaterial(string liquid)
|
||||||
|
{
|
||||||
|
return WildcardMatch("Oil", liquid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public func QueryConnectPipe(object pipe)
|
||||||
|
{
|
||||||
|
if (pipe->IsDrainPipe() || pipe->IsNeutralPipe())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pipe->Report("$MsgPipeProhibited$");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func OnPipeConnect(object pipe, string specific_pipe_state)
|
||||||
|
{
|
||||||
|
SetNeutralPipe(pipe);
|
||||||
|
pipe->Report("$MsgConnectedPipe$");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Interaction Interface --*/
|
||||||
|
|
||||||
|
public func GetOilAmount()
|
||||||
|
{
|
||||||
|
var oil = FindObject(Find_ID(Oil), Find_Container(this));
|
||||||
|
if (oil)
|
||||||
|
return oil->GetStackCount() / 1000;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func HasInteractionMenu() { return true; }
|
||||||
|
|
||||||
|
public func GetInteractionMenus(object clonk)
|
||||||
|
{
|
||||||
|
var menus = _inherited() ?? [];
|
||||||
|
var oil_menu =
|
||||||
|
{
|
||||||
|
title = "$MsgOilOverview$",
|
||||||
|
entries_callback = this.GetOilDisplayMenuEntries,
|
||||||
|
callback_hover = "OnOilDisplayHover",
|
||||||
|
callback_target = this,
|
||||||
|
BackgroundColor = RGB(0, 50, 50),
|
||||||
|
Priority = 20
|
||||||
|
};
|
||||||
|
PushBack(menus, oil_menu);
|
||||||
|
return menus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func GetOilDisplayMenuEntries(object clonk)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
[{
|
||||||
|
symbol = Oil,
|
||||||
|
extra_data = "oil",
|
||||||
|
custom = {
|
||||||
|
Style = GUI_FitChildren | GUI_TextVCenter | GUI_TextLeft,
|
||||||
|
Bottom = "1.1em",
|
||||||
|
BackgroundColor = {Std = 0, OnHover = 0x50ff0000},
|
||||||
|
Priority = 1,
|
||||||
|
Text = Format("$MsgOilPumped$", GetOilAmount())
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
public func OnOilDisplayHover(id symbol, string extra_data, desc_menu_target, menu_id)
|
||||||
|
{
|
||||||
|
GuiUpdateText(Format("$MsgOilDescription$", GetOilAmount()), menu_id, 1, desc_menu_target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Properties --*/
|
||||||
|
|
||||||
|
local Name = "$Name$";
|
||||||
|
local Description = "$Description$";
|
|
@ -0,0 +1,9 @@
|
||||||
|
Name=Raffinerie Drain
|
||||||
|
Description=Attach the drain pipe of a pump to this structure to pump oil into the refinery. Multiple pipes can be connected to the refinery drain.
|
||||||
|
|
||||||
|
MsgOilOverview=Oil Overview
|
||||||
|
MsgOilPumped=Oil amount: %d {{Oil}}.
|
||||||
|
MsgOilDescription=Currently %d {{Oil}} has been transferred into the refinery.
|
||||||
|
|
||||||
|
MsgConnectedPipe=Rohr angeschlossen.
|
||||||
|
MsgPipeProhibited=Zuflussrohre können nicht an den Raffinerie angeschlossen werden.
|
|
@ -0,0 +1,9 @@
|
||||||
|
Name=Refinery Drain
|
||||||
|
Description=Attach the drain pipe of a pump to this structure to pump oil into the refinery. Multiple pipes can be connected to the refinery drain.
|
||||||
|
|
||||||
|
MsgOilOverview=Oil Overview
|
||||||
|
MsgOilPumped=Oil amount: %d {{Oil}}.
|
||||||
|
MsgOilDescription=Currently %d {{Oil}} has been transferred into the refinery.
|
||||||
|
|
||||||
|
MsgConnectedPipe=Connected pipe.
|
||||||
|
MsgPipeProhibited=Source pipes cannot be connected to the foundry.
|
|
@ -0,0 +1,5 @@
|
||||||
|
[DefCore]
|
||||||
|
id=Goal_Refinery
|
||||||
|
Version=6,0
|
||||||
|
Category=C4D_StaticBack|C4D_Goal
|
||||||
|
Picture=0,0,128,128
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
Refinery Goal
|
||||||
|
A certain amount of oil has to be pumped into the refinery drain.
|
||||||
|
|
||||||
|
@author Maikel
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include Library_Goal
|
||||||
|
|
||||||
|
local goal_amount;
|
||||||
|
|
||||||
|
protected func Initialize()
|
||||||
|
{
|
||||||
|
goal_amount = 0;
|
||||||
|
return _inherited(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
public func SetGoalAmount(int amount)
|
||||||
|
{
|
||||||
|
goal_amount = amount;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private func GetPumpedAmount()
|
||||||
|
{
|
||||||
|
var refinery_drain = FindObject(Find_ID(RefineryDrain));
|
||||||
|
if (!refinery_drain)
|
||||||
|
return 0;
|
||||||
|
return refinery_drain->GetOilAmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public func IsFulfilled()
|
||||||
|
{
|
||||||
|
return GetPumpedAmount() >= goal_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public func GetDescription(int plr)
|
||||||
|
{
|
||||||
|
if (IsFulfilled())
|
||||||
|
return "$DescriptionCompleted$";
|
||||||
|
return Format("$Description$", GetPumpedAmount(), goal_amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Proplist --*/
|
||||||
|
|
||||||
|
local Name = "$Name$";
|
||||||
|
local Description = "$Description$";
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name=Raffinerie
|
||||||
|
Description=You have currently pumped %d {{Oil}} into the refinery drain out of the %d {{Oil}} needed to fulfill this goal.
|
||||||
|
DescriptionCompleted=Congratulations! You have pumped enough oil into the refinery drain.
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name=Refinery
|
||||||
|
Description=You have currently pumped %d {{Oil}} into the refinery drain out of the %d {{Oil}} needed to fulfill this goal.
|
||||||
|
DescriptionCompleted=Congratulations! You have pumped enough oil into the refinery drain.
|
|
@ -0,0 +1,31 @@
|
||||||
|
[Head]
|
||||||
|
Title=RapidRefining
|
||||||
|
Icon=24
|
||||||
|
Version=6,0
|
||||||
|
Difficulty=50
|
||||||
|
|
||||||
|
[Definitions]
|
||||||
|
Definition1=Objects.ocd
|
||||||
|
|
||||||
|
[Player1]
|
||||||
|
Crew=Clonk=2
|
||||||
|
|
||||||
|
[Player2]
|
||||||
|
Crew=Clonk=2
|
||||||
|
|
||||||
|
[Player3]
|
||||||
|
Crew=Clonk=2
|
||||||
|
|
||||||
|
[Player4]
|
||||||
|
Crew=Clonk=2
|
||||||
|
|
||||||
|
[Landscape]
|
||||||
|
Sky=Clouds1
|
||||||
|
TopOpen=0
|
||||||
|
BottomOpen=0
|
||||||
|
|
||||||
|
[Weather]
|
||||||
|
Climate=0
|
||||||
|
YearSpeed=0
|
||||||
|
Wind=0,50,-50,50
|
||||||
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
/**
|
||||||
|
Rapid Refining
|
||||||
|
Use the oil from an underground well to power your settlement.
|
||||||
|
|
||||||
|
@author Maikel
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Whether the intro has been initialized.
|
||||||
|
static intro_init;
|
||||||
|
|
||||||
|
// Whether the first players has been initialized.
|
||||||
|
static first_plr_init;
|
||||||
|
|
||||||
|
protected func Initialize()
|
||||||
|
{
|
||||||
|
// Show wealth in HUD.
|
||||||
|
GUI_Controller->ShowWealth();
|
||||||
|
|
||||||
|
// Rules: team account and buying at flagpole.
|
||||||
|
CreateObject(Rule_TeamAccount);
|
||||||
|
CreateObject(Rule_BuyAtFlagpole);
|
||||||
|
|
||||||
|
// Goal: pump oil into refinery drain.
|
||||||
|
var goal = CreateObject(Goal_Refinery);
|
||||||
|
var amount = 400;
|
||||||
|
if (SCENPAR_Difficulty == 2)
|
||||||
|
amount = 800;
|
||||||
|
else if (SCENPAR_Difficulty == 3)
|
||||||
|
amount = 1600;
|
||||||
|
goal->SetGoalAmount(amount);
|
||||||
|
|
||||||
|
// Initialize different parts of the scenario.
|
||||||
|
InitEnvironment(SCENPAR_Difficulty);
|
||||||
|
InitVegetation(SCENPAR_MapSize);
|
||||||
|
InitAnimals(SCENPAR_MapSize, SCENPAR_Difficulty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected func OnGoalsFulfilled()
|
||||||
|
{
|
||||||
|
// Give the remaining players their achievement.
|
||||||
|
GainScenarioAchievement("Done", BoundBy(SCENPAR_Difficulty, 1, 3));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Player Initialization --*/
|
||||||
|
|
||||||
|
protected func InitializePlayer(int plr)
|
||||||
|
{
|
||||||
|
// Harsh zoom range.
|
||||||
|
SetPlayerZoomByViewRange(plr, 400, nil, PLRZOOM_Direct | PLRZOOM_LimitMax);
|
||||||
|
SetPlayerViewLock(plr, true);
|
||||||
|
SetFoW(false, plr);
|
||||||
|
|
||||||
|
// First player inits the base.
|
||||||
|
if (!first_plr_init)
|
||||||
|
{
|
||||||
|
InitBase(plr, 4 - SCENPAR_Difficulty);
|
||||||
|
first_plr_init = true;
|
||||||
|
// Give only the first joined player some wealth.
|
||||||
|
SetWealth(plr, 150 - 50 * SCENPAR_Difficulty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position and materials for the crew.
|
||||||
|
var crew;
|
||||||
|
for (var i = 0; crew = GetCrew(plr, i); ++i)
|
||||||
|
{
|
||||||
|
crew->SetPosition(20 + Random(32), 160 - 10);
|
||||||
|
crew->CreateContents(Shovel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give the player basic and pumping knowledge.
|
||||||
|
GivePlayerBasicKnowledge(plr);
|
||||||
|
GivePlayerPumpingKnowledge(plr);
|
||||||
|
GivePlayerWeaponryKnowledge(plr);
|
||||||
|
GivePlayerAdvancedKnowledge(plr);
|
||||||
|
GivePlayerFarmingKnowledge(plr);
|
||||||
|
RemovePlayerSpecificKnowledge(plr, [WindGenerator]);
|
||||||
|
|
||||||
|
// Give the player the elementary base materials.
|
||||||
|
GivePlayerElementaryBaseMaterial(plr);
|
||||||
|
GivePlayerToolsBaseMaterial(plr);
|
||||||
|
|
||||||
|
// Initialize the intro sequence if not yet started.
|
||||||
|
if (!intro_init)
|
||||||
|
{
|
||||||
|
//StartSequence("Intro", 0);
|
||||||
|
intro_init = true;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private func InitBase(int owner, int amount)
|
||||||
|
{
|
||||||
|
var y = 160;
|
||||||
|
|
||||||
|
// The basic settlement: flagpole, wind generator, chest.
|
||||||
|
CreateObjectAbove(Flagpole, 184, y, owner);
|
||||||
|
var chest = CreateObjectAbove(Chest, 202, y, owner);
|
||||||
|
chest->CreateContents(Hammer, 2);
|
||||||
|
chest->CreateContents(Axe, 2);
|
||||||
|
CreateObjectAbove(WindGenerator, 222, y, owner);
|
||||||
|
|
||||||
|
// Two pumps connected to the refinery drain.
|
||||||
|
var refinery_exit = CreateObjectAbove(RefineryDrain, 8, y, owner);
|
||||||
|
var pump1 = CreateObjectAbove(Pump, 250, y, owner);
|
||||||
|
var pump2 = CreateObjectAbove(Pump, 284, y, owner);
|
||||||
|
var pipe1 = pump1->CreateObject(Pipe);
|
||||||
|
pipe1->ConnectPipeTo(pump1);
|
||||||
|
pipe1 = pump1->CreateObject(Pipe, 8);
|
||||||
|
pipe1->ConnectPipeTo(pump1);
|
||||||
|
pipe1->ConnectPipeTo(refinery_exit);
|
||||||
|
var pipe2 = pump2->CreateObject(Pipe, 8);
|
||||||
|
pipe2->ConnectPipeTo(pump2);
|
||||||
|
pipe2 = pump2->CreateObject(Pipe, -8);
|
||||||
|
pipe2->ConnectPipeTo(pump2);
|
||||||
|
|
||||||
|
// Additional material in the chest.
|
||||||
|
if (amount >= 2)
|
||||||
|
{
|
||||||
|
chest->CreateContents(Wood, 12);
|
||||||
|
chest->CreateContents(Metal, 8);
|
||||||
|
chest->CreateContents(Dynamite, 4);
|
||||||
|
if (amount >= 3)
|
||||||
|
{
|
||||||
|
chest->CreateContents(Wood, 12);
|
||||||
|
chest->CreateContents(Metal, 8);
|
||||||
|
chest->CreateContents(Loam, 4);
|
||||||
|
chest->CreateContents(Pickaxe, 2);
|
||||||
|
chest->CreateContents(Bread, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Scenario Initialization --*/
|
||||||
|
|
||||||
|
private func InitEnvironment(int difficulty)
|
||||||
|
{
|
||||||
|
// Sky has some parallax.
|
||||||
|
SetSkyParallax(1, 20, 20);
|
||||||
|
|
||||||
|
// Some earthquakes if difficulty prescribes it.
|
||||||
|
if (difficulty >= 2)
|
||||||
|
Earthquake->SetChance(4 * (difficulty - 1));
|
||||||
|
|
||||||
|
// A waterfall above the underground lake.
|
||||||
|
var waterfall_x = 50;
|
||||||
|
var waterfall_y = LandscapeHeight() - 600;
|
||||||
|
var trunk = CreateObjectAbove(Trunk, waterfall_x, waterfall_y);
|
||||||
|
trunk->DoCon(30); trunk->SetR(150); trunk.Plane = 510;
|
||||||
|
trunk.MeshTransformation = [-70, 0, 998, 0, 0, 1000, 0, 0, -998, 0, -70, 0];
|
||||||
|
trunk->MakeInvincible();
|
||||||
|
|
||||||
|
var waterfall = CreateWaterfall(waterfall_x + 22, waterfall_y - 10, 10, "Water");
|
||||||
|
waterfall->SetDirection(2, 0, 3, 6);
|
||||||
|
waterfall->SetSoundLocation(waterfall_x + 40, waterfall_y + 240);
|
||||||
|
|
||||||
|
CreateLiquidDrain(8, 1040, 10);
|
||||||
|
CreateLiquidDrain(16, 1040, 10);
|
||||||
|
CreateLiquidDrain(24, 1040, 10);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private func InitVegetation(int map_size)
|
||||||
|
{
|
||||||
|
var wdt = LandscapeWidth();
|
||||||
|
var hgt = LandscapeHeight();
|
||||||
|
|
||||||
|
// Some plants and trees on the outside.
|
||||||
|
Tree_Deciduous->Place(16, Shape->Rectangle(0, 0, 240, 160));
|
||||||
|
Tree_Coniferous2->Place(2, Shape->Rectangle(0, 0, 240, 160));
|
||||||
|
Cotton->Place(4, Shape->Rectangle(0, 0, 240, 160));
|
||||||
|
SproutBerryBush->Place(2, Shape->Rectangle(0, 0, 240, 160));
|
||||||
|
Grass->Place(100);
|
||||||
|
|
||||||
|
// Some plants and in the caves.
|
||||||
|
LargeCaveMushroom->Place(40 + 6 * map_size, nil, {terraform = false});
|
||||||
|
Fern->Place(40 + 6 * map_size);
|
||||||
|
Mushroom->Place(40 + 6 * map_size);
|
||||||
|
Branch->Place(20 + 3 * map_size);
|
||||||
|
|
||||||
|
// Some objects in the earth.
|
||||||
|
PlaceObjects(Rock, 40 + 10 * map_size + Random(5),"Earth");
|
||||||
|
PlaceObjects(Firestone, 40 + 10 * map_size + Random(5), "Earth");
|
||||||
|
PlaceObjects(Loam, 40 + 10 * map_size + Random(5), "Earth");
|
||||||
|
|
||||||
|
// Underwater plants.
|
||||||
|
var place_rect = Shape->Rectangle(0, 2 * hgt / 3, wdt / 4, hgt / 3);
|
||||||
|
Seaweed->Place(12, place_rect);
|
||||||
|
Coral->Place(8, place_rect);
|
||||||
|
|
||||||
|
// Place some diamonds in the hard to reach location.
|
||||||
|
Diamond->Place(20, Shape->Rectangle(5 * wdt / 6, 0, wdt / 6, hgt / 4));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private func InitAnimals(int map_size, int difficulty)
|
||||||
|
{
|
||||||
|
var wdt = LandscapeWidth();
|
||||||
|
var hgt = LandscapeHeight();
|
||||||
|
|
||||||
|
// Some butterflies as atmosphere.
|
||||||
|
for (var i = 0; i < 8; i++)
|
||||||
|
PlaceAnimal(Butterfly);
|
||||||
|
|
||||||
|
// Some wipfs underground.
|
||||||
|
Wipf->Place(10);
|
||||||
|
|
||||||
|
// Place some fishes and piranhas as difficulty prescribes it.
|
||||||
|
var place_rect = Shape->Rectangle(0, 2 * hgt / 3, wdt / 4, hgt / 3);
|
||||||
|
var fish_count = 15;
|
||||||
|
Fish->Place(fish_count * (3 - difficulty), place_rect);
|
||||||
|
Piranha->Place(fish_count * (difficulty - 1), place_rect);
|
||||||
|
|
||||||
|
// Bats on higher difficulty.
|
||||||
|
if (difficulty >= 2)
|
||||||
|
Bat->Place((difficulty - 1) * 12, Shape->Rectangle(2 * wdt / 3, 0, wdt / 3, hgt));
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Scenario parameters: difficulty
|
||||||
|
Difficulty=Schwierigkeit
|
||||||
|
DescDifficulty=Setzt die Schwierigkeit dieser Runde.
|
||||||
|
DiffNormal=Normal
|
||||||
|
DescDiffNormal=Die Schwierigkeit dieser Runde ist normal.
|
||||||
|
DiffHard=Schwer
|
||||||
|
DescDiffHard=Die Schwierigkeit dieser Runde ist schwer.
|
||||||
|
DiffInsane=Irrsinnig
|
||||||
|
DescDiffInsane=Die Schwierigkeit dieser Runde ist irrsinnig.
|
||||||
|
|
||||||
|
# Scenario parameters: map size
|
||||||
|
MapSize=Kartengröße
|
||||||
|
DescMapSize=Setzt die Kartengröße dieser Runde.
|
||||||
|
MapSmall=Klein
|
||||||
|
DescMapSmall=Die Karte dieser Runde wird klein sein
|
||||||
|
MapAverage=Durchschnittlich
|
||||||
|
DescMapAverage=Die Karte dieser Runde wird durchschnittlich sein.
|
||||||
|
MapLarge=Groß
|
||||||
|
DescMapLarge=Die Karte dieser Runde wird groß sein.
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Scenario parameters: difficulty
|
||||||
|
Difficulty=Difficulty
|
||||||
|
DescDifficulty=Sets this round's difficulty.
|
||||||
|
DiffNormal=Normal
|
||||||
|
DescDiffNormal=This round's difficulty will be set to normal.
|
||||||
|
DiffHard=Hard
|
||||||
|
DescDiffHard=This round's difficulty will be set to hard.
|
||||||
|
DiffInsane=Insane
|
||||||
|
DescDiffInsane=This round's difficulty will be set to insane.
|
||||||
|
|
||||||
|
# Scenario parameters: map size
|
||||||
|
MapSize=Map size
|
||||||
|
DescMapSize=Sets this round's map size.
|
||||||
|
MapSmall=Small
|
||||||
|
DescMapSmall=This round's map will be small.
|
||||||
|
MapAverage=Average
|
||||||
|
DescMapAverage=This round's map will be average.
|
||||||
|
MapLarge=Large
|
||||||
|
DescMapLarge=This round's map will be large.
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Maximum pipe length depends on difficulty.
|
||||||
|
|
||||||
|
#appendto PipeLine
|
||||||
|
|
||||||
|
public func Definition(proplist def)
|
||||||
|
{
|
||||||
|
def.PipeMaxLength = def.PipeMaxLength * (12 - 2 * SCENPAR_Difficulty) / 10;
|
||||||
|
return;
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 91 KiB |
|
@ -0,0 +1,2 @@
|
||||||
|
DE:Rasches Raffinieren
|
||||||
|
US:Rapid Refining
|
|
@ -62,6 +62,7 @@ don't need to include this file or any of the files it includes. */
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "lib/Standard.h"
|
#include "lib/Standard.h"
|
||||||
#include "C4Prototypes.h"
|
#include "C4Prototypes.h"
|
||||||
|
|
Loading…
Reference in New Issue