Merge branch 'master' of ssh://git.openclonk.org/openclonk
Conflicts: src/editor/C4ConsoleQtPropListViewer.cppalut-include-path
|
@ -1 +1,2 @@
|
|||
node: $Format:%H$
|
||||
date: $Format:%ci$
|
||||
|
|
|
@ -721,6 +721,8 @@ set(OC_CLONK_SOURCES
|
|||
src/platform/PlatformAbstraction.cpp
|
||||
src/platform/PlatformAbstraction.h
|
||||
src/platform/StdSync.h
|
||||
src/player/C4Achievement.cpp
|
||||
src/player/C4Achievement.h
|
||||
src/player/C4Player.cpp
|
||||
src/player/C4Player.h
|
||||
src/player/C4PlayerList.cpp
|
||||
|
@ -1512,12 +1514,16 @@ foreach(group ${OC_C4GROUPS})
|
|||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT APPLE)
|
||||
# group files (game data)
|
||||
add_custom_target(groups DEPENDS ${OC_C4GROUPS})
|
||||
set_property(TARGET groups PROPERTY FOLDER "Setup")
|
||||
add_dependencies(data groups)
|
||||
# Install binaries
|
||||
install(TARGETS c4group DESTINATION bin)
|
||||
endif()
|
||||
if(NOT HEADLESS_ONLY)
|
||||
if(NOT APPLE)
|
||||
add_custom_target(groups DEPENDS ${OC_C4GROUPS})
|
||||
set_property(TARGET groups PROPERTY FOLDER "Setup")
|
||||
add_dependencies(data groups)
|
||||
|
||||
# Install new files
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/openclonk.desktop DESTINATION share/applications)
|
||||
# Update the MIME cache -- this makes the clonk:// protocol handler actually work
|
||||
|
@ -1528,7 +1534,6 @@ if(NOT HEADLESS_ONLY)
|
|||
|
||||
# Install binaries
|
||||
install(TARGETS openclonk DESTINATION games)
|
||||
install(TARGETS c4group DESTINATION bin)
|
||||
else()
|
||||
install(TARGETS openclonk
|
||||
BUNDLE DESTINATION .
|
||||
|
|
|
@ -28,6 +28,20 @@ function(git_get_changeset_id VAR)
|
|||
OUTPUT_VARIABLE GIT_STATUS
|
||||
)
|
||||
string(REGEX MATCH "^[MADRC ][MD ]" WORKDIR_DIRTY "${GIT_STATUS}")
|
||||
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND "${GIT_EXECUTABLE}" "rev-parse" "--git-path" "index"
|
||||
OUTPUT_VARIABLE GIT_INDEX
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
|
||||
"${GIT_INDEX}"
|
||||
)
|
||||
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND "${GIT_EXECUTABLE}" "show" "--format=%ci" "-s" "HEAD"
|
||||
OUTPUT_VARIABLE GIT_TIMESTAMP
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if (NOT C4REVISION)
|
||||
|
@ -44,9 +58,17 @@ function(git_get_changeset_id VAR)
|
|||
string(SUBSTRING "${C4REVISION}" 6 12 C4REVISION)
|
||||
endif()
|
||||
unset(revlength)
|
||||
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/.git_archival" C4REVISION_TS
|
||||
LIMIT_COUNT 1
|
||||
REGEX "date: .+"
|
||||
)
|
||||
string(SUBSTRING "${C4REVISION_TS}" 6 -1 GIT_TIMESTAMP)
|
||||
endif()
|
||||
if(WORKDIR_DIRTY)
|
||||
set(C4REVISION "${C4REVISION}+")
|
||||
set(WORKDIR_DIRTY 1)
|
||||
endif()
|
||||
set(${VAR} "${C4REVISION}" PARENT_SCOPE)
|
||||
set(${VAR}_DIRTY ${WORKDIR_DIRTY} PARENT_SCOPE)
|
||||
set(${VAR}_TS "${GIT_TIMESTAMP}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!DOCTYPE funcs
|
||||
SYSTEM '../../../clonk.dtd'>
|
||||
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
|
||||
<funcs>
|
||||
<func>
|
||||
<title>ParseInt</title>
|
||||
<category>Script</category>
|
||||
<subcat>Strings</subcat>
|
||||
<version>8.0 OC</version>
|
||||
<syntax>
|
||||
<rtype>int</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>string</type>
|
||||
<name>value</name>
|
||||
<desc>string representation of a number to parse</desc>
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Parses a string representing a base 10 number into an integer value. If the string does not entirely consist of a base 10 number, optionally signed, <code>nil</code> is returned.</desc>
|
||||
<examples>
|
||||
<example>
|
||||
<code>ParseInt("14")</code>
|
||||
<text>Returns the integer <code>14</code>.</text>
|
||||
<code>ParseInt("fourteen")</code>
|
||||
<text>Returns <code>nil</code>.</text>
|
||||
</example>
|
||||
</examples>
|
||||
</func>
|
||||
</funcs>
|
|
@ -7,9 +7,6 @@
|
|||
*/
|
||||
|
||||
|
||||
// List for storing the different large caves.
|
||||
static cave_list;
|
||||
|
||||
// Game modes.
|
||||
static const GAMEMODE_Deathmatch = 0;
|
||||
static const GAMEMODE_LastManStanding = 1;
|
||||
|
@ -19,18 +16,31 @@ protected func Initialize()
|
|||
{
|
||||
// Goals and rules.
|
||||
if (SCENPAR_GameMode == GAMEMODE_Deathmatch)
|
||||
{
|
||||
CreateObject(Goal_DeathMatch);
|
||||
GetRelaunchRule()->SetDefaultRelaunchCount(Max(SCENPAR_NrRelaunchesKills, 0));
|
||||
}
|
||||
else if (SCENPAR_GameMode == GAMEMODE_LastManStanding)
|
||||
{
|
||||
CreateObject(Goal_LastManStanding);
|
||||
GetRelaunchRule()->SetDefaultRelaunchCount(Max(SCENPAR_NrRelaunchesKills, 0));
|
||||
}
|
||||
|
||||
else if (SCENPAR_GameMode == GAMEMODE_KingOfTheHill)
|
||||
{
|
||||
var goal = CreateObject(Goal_KingOfTheHill, LandscapeWidth() / 2, LandscapeHeight() / 2);
|
||||
goal->SetRadius(72);
|
||||
goal->SetPointLimit(Max(SCENPAR_NrRelaunchesKills, 1));
|
||||
GetRelaunchRule()->SetDefaultRelaunchCount(nil);
|
||||
}
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_Gravestones);
|
||||
|
||||
GetRelaunchRule()
|
||||
->SetLastWeaponUse(false)
|
||||
->SetFreeCrew(true)
|
||||
->SetRespawnDelay(4);
|
||||
|
||||
// Rescale cave coordinates with map zoom and shuffle them.
|
||||
var mapzoom = GetScenarioVal("MapZoom", "Landscape");
|
||||
for (var cave in cave_list)
|
||||
|
@ -53,13 +63,6 @@ protected func Initialize()
|
|||
return;
|
||||
}
|
||||
|
||||
// Callback from the last man standing goal.
|
||||
protected func RelaunchCount()
|
||||
{
|
||||
// Relaunch count depends on scenario setting.
|
||||
return Max(SCENPAR_NrRelaunchesKills, 0);
|
||||
}
|
||||
|
||||
// Callback from the last man standing goal.
|
||||
protected func KillsToRelaunch()
|
||||
{
|
||||
|
@ -73,46 +76,23 @@ public func WinKillCount()
|
|||
return Max(SCENPAR_NrRelaunchesKills, 1);
|
||||
}
|
||||
|
||||
// Forward callbacks to OnPlayerRelaunch for KotH goal.
|
||||
protected func InitializePlayer(int plr)
|
||||
public func RelaunchPosition(int plr)
|
||||
{
|
||||
if (SCENPAR_GameMode == GAMEMODE_KingOfTheHill)
|
||||
GameCall("OnPlayerRelaunch", plr, false);
|
||||
return _inherited(plr, ...);
|
||||
return FindStartCave(plr, GetRelaunchRule()->GetPlayerRelaunchCount(plr) != SCENPAR_NrRelaunchesKills);
|
||||
}
|
||||
|
||||
// Forward callbacks to OnPlayerRelaunch for KotH goal.
|
||||
protected func RelaunchPlayer(int plr, int killer)
|
||||
public func OnClonkLeftRelaunch(object clonk, int plr)
|
||||
{
|
||||
if (SCENPAR_GameMode == GAMEMODE_KingOfTheHill)
|
||||
{
|
||||
var clonk = CreateObjectAbove(Clonk, 0, 0, plr);
|
||||
clonk->MakeCrewMember(plr);
|
||||
SetCursor(plr, clonk);
|
||||
clonk->DoEnergy(100000);
|
||||
GameCall("OnPlayerRelaunch", plr, true);
|
||||
}
|
||||
return _inherited(plr, killer);
|
||||
}
|
||||
|
||||
// Callback from the last man standing and deathmatch goal.
|
||||
// Takes over the role of initializing the player.
|
||||
protected func OnPlayerRelaunch(int plr, bool is_relaunch)
|
||||
{
|
||||
// Get the only clonk of the player.
|
||||
var clonk = GetCrew(plr);
|
||||
|
||||
// Players start in a random small cave, the cave depends on whether it is a relaunch.
|
||||
var cave = FindStartCave(plr, is_relaunch);
|
||||
clonk->SetPosition(cave[0], cave[1]);
|
||||
// Ensure spawn position is free
|
||||
for (var i=0; i<4; ++i) BlastFree(cave[0], cave[1], 13);
|
||||
var cave = [clonk->GetX(), clonk->GetY()];
|
||||
for (var i = 0; i < 4; ++i)
|
||||
BlastFree(cave[0], cave[1], 13);
|
||||
|
||||
// Players start with a shovel, a pickaxe and two firestones.
|
||||
clonk->CreateContents(Shovel);
|
||||
clonk->CreateContents(Pickaxe);
|
||||
// Better weapons after relaunching.
|
||||
if (!is_relaunch)
|
||||
if (GetRelaunchRule()->GetPlayerRelaunchCount(plr) != SCENPAR_NrRelaunchesKills)
|
||||
{
|
||||
clonk->CreateContents(Torch);
|
||||
clonk->CreateContents(Firestone, 2);
|
||||
|
|
|
@ -10,6 +10,9 @@ protected func Initialize()
|
|||
{
|
||||
// Environment
|
||||
CreateObject(Rule_ObjectFade)->DoFadeTime(10 * 36);
|
||||
|
||||
GetRelaunchRule()->SetLastWeaponUse(false);
|
||||
|
||||
var time=CreateObject(Time);
|
||||
time->SetTime();
|
||||
time->SetCycleSpeed();
|
||||
|
@ -151,16 +154,6 @@ protected func InitializePlayer(int plr)
|
|||
return;
|
||||
}
|
||||
|
||||
// Gamecall from CTF goal, on respawning.
|
||||
protected func OnPlayerRelaunch(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, clonk->GetX(), clonk->GetY(), clonk->GetOwner());
|
||||
relaunch->StartRelaunch(clonk);
|
||||
relaunch->SetRelaunchTime(8, true);
|
||||
return;
|
||||
}
|
||||
|
||||
func RelaunchWeaponList() { return [Blunderbuss, Sword, Javelin, FrostboltScroll, Shovel]; }
|
||||
|
||||
/*-- Chest filler effects --*/
|
||||
|
|
|
@ -14,17 +14,19 @@ protected func Initialize()
|
|||
|
||||
// Goal: Capture the flag, with bases in both hideouts.
|
||||
var goal = CreateObject(Goal_CaptureTheFlag, 0, 0, NO_OWNER);
|
||||
goal->SetFlagBase(1, 120, 502);
|
||||
goal->SetFlagBase(2, LandscapeWidth() - 120, 502);
|
||||
goal->SetFlagBase(1, 120, 506);
|
||||
goal->SetFlagBase(2, LandscapeWidth() - 120, 506);
|
||||
|
||||
// Rules
|
||||
CreateObject(Rule_Restart);
|
||||
var relaunch_rule = GetRelaunchRule();
|
||||
relaunch_rule->SetAllowPlayerRestart(true);
|
||||
relaunch_rule->SetRespawnDelay(8);
|
||||
relaunch_rule->SetLastWeaponUse(false);
|
||||
CreateObject(Rule_ObjectFade)->DoFadeTime(5 * 36);
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_Gravestones);
|
||||
|
||||
|
||||
var lwidth = LandscapeWidth();
|
||||
|
||||
// Doors and spinwheels.
|
||||
var gate, wheel;
|
||||
gate = CreateObjectAbove(StoneDoor, 364, 448, NO_OWNER);
|
||||
|
@ -100,16 +102,6 @@ protected func InitializePlayer(int plr)
|
|||
return;
|
||||
}
|
||||
|
||||
// Gamecall from CTF goal, on respawning.
|
||||
protected func OnPlayerRelaunch(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, clonk->GetX(), clonk->GetY(), clonk->GetOwner());
|
||||
relaunch->StartRelaunch(clonk);
|
||||
relaunch->SetRelaunchTime(8, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Game call from RelaunchContainer when a Clonk has left the respawn.
|
||||
public func OnClonkLeftRelaunch(object clonk)
|
||||
{
|
||||
|
|
|
@ -47,7 +47,9 @@ func Initialize()
|
|||
g_goal = CreateObject(Goal_BeRich);
|
||||
|
||||
CreateObject(Rule_BuyAtFlagpole);
|
||||
CreateObject(Rule_BaseRespawn);
|
||||
GetRelaunchRule()
|
||||
->SetBaseRespawn(true)
|
||||
->SetLastClonkRespawn(true);
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_TeamAccount);
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@ func InitializeObjects()
|
|||
{
|
||||
CreateObject(Rule_KillLogs, 50, 50);
|
||||
CreateObject(Rule_Gravestones, 50, 50);
|
||||
CreateObject(Rule_Restart, 50, 50);
|
||||
|
||||
|
||||
CreateObject(Goal_Melee, 50, 50);
|
||||
|
||||
ItemSpawn->Create(Firestone,407,389);
|
||||
|
|
|
@ -7,6 +7,10 @@ static const EDIT_MAP = false; // Set to true to edit map and Objects.c; avoids
|
|||
func Initialize()
|
||||
{
|
||||
if (EDIT_MAP) return true;
|
||||
GetRelaunchRule()->SetDefaultRelaunchCount(nil);
|
||||
GetRelaunchRule()->SetRespawnDelay(8);
|
||||
GetRelaunchRule()->SetLastWeaponUse(false);
|
||||
GetRelaunchRule()->SetAllowPlayerRestart(true);
|
||||
// Mirror map objects by moving them to the other side, then re-running object initialization
|
||||
for (var o in FindObjects(Find_NoContainer(), Find_Not(Find_Category(C4D_Goal | C4D_Rule))))
|
||||
{
|
||||
|
@ -105,7 +109,6 @@ func InitializePlayer(int plr)
|
|||
ScheduleCall(nil, Scenario.IntroMsg, 10, 1);
|
||||
}
|
||||
// Initial launch
|
||||
RelaunchPlayer(plr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -125,56 +128,39 @@ func IntroMsg()
|
|||
return true;
|
||||
}
|
||||
|
||||
func LaunchPlayer(int plr)
|
||||
func LaunchPlayer(object clonk, int plr)
|
||||
{
|
||||
// Position at flag
|
||||
var flagpole = g_respawn_flags[GetPlayerTeam(plr)];
|
||||
if (!flagpole) return EliminatePlayer(plr); // Flag lost and clonk died? Game over!
|
||||
var crew = GetCrew(plr), start_x = flagpole->GetX(), start_y = flagpole->GetY();
|
||||
crew->SetPosition(start_x, start_y);
|
||||
// Make sure clonk can move
|
||||
DigFreeRect(start_x-6,start_y-10,13,18,true);
|
||||
DigFreeRect(clonk->GetX()-6,clonk->GetY()-10,13,18,true);
|
||||
// Crew setup
|
||||
crew.MaxEnergy = 100000;
|
||||
crew->DoEnergy(1000);
|
||||
crew->CreateContents(WindBag);
|
||||
clonk.MaxEnergy = 100000;
|
||||
clonk->DoEnergy(1000);
|
||||
clonk->CreateContents(WindBag);
|
||||
return true;
|
||||
}
|
||||
|
||||
func RelaunchPlayer(int plr)
|
||||
public func OnPlayerRelaunch(int plr)
|
||||
{
|
||||
if (!g_respawn_flags[GetPlayerTeam(plr)])
|
||||
return EliminatePlayer(plr);
|
||||
}
|
||||
|
||||
public func RelaunchPosition(int iPlr, int iTeam)
|
||||
{
|
||||
if(!g_respawn_flags[iTeam]) return;
|
||||
return [g_respawn_flags[iTeam]->GetX(), g_respawn_flags[iTeam]->GetY()];
|
||||
}
|
||||
|
||||
public func OnClonkLeftRelaunch(object clonk, int plr)
|
||||
{
|
||||
// Find flag for respawn
|
||||
var flagpole = g_respawn_flags[GetPlayerTeam(plr)];
|
||||
if (!flagpole) return EliminatePlayer(plr); // Flag lost and clonk died? Game over!
|
||||
// Player positioning.
|
||||
var start_x = flagpole->GetX(), start_y = flagpole->GetY();
|
||||
// Relaunch: New clonk
|
||||
var crew = GetCrew(plr);
|
||||
var is_relaunch = (!crew || !crew->GetAlive());
|
||||
if (is_relaunch)
|
||||
{
|
||||
crew = CreateObject(Clonk, 10,10, plr);
|
||||
if (!crew) return false; // wat?
|
||||
crew->MakeCrewMember(plr);
|
||||
SetCursor(plr, crew, false);
|
||||
}
|
||||
|
||||
// Reset available items in spawns
|
||||
for (var item_spawn in FindObjects(Find_ID(ItemSpawn))) item_spawn->Reset(plr);
|
||||
// Relaunch near current flag pos (will be adjusted on actual relaunch)
|
||||
crew->SetPosition(start_x, start_y);
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, start_x, start_y, plr);
|
||||
if (relaunch)
|
||||
{
|
||||
relaunch->StartRelaunch(crew);
|
||||
relaunch->SetRelaunchTime(8, is_relaunch);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// GameCall from RelaunchContainer.
|
||||
func OnClonkLeftRelaunch(object clonk)
|
||||
{
|
||||
if (clonk) return LaunchPlayer(clonk->GetOwner());
|
||||
return LaunchPlayer(clonk, plr);
|
||||
}
|
||||
|
||||
func RelaunchWeaponList() { return [Bow, Sword, Club, Javelin, Blunderbuss, Firestone, IceWallKit]; }
|
||||
|
|
|
@ -18,6 +18,7 @@ protected func Initialize()
|
|||
CreateObject(Rule_ObjectFade)->DoFadeTime(7 * 36);
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_Gravestones);
|
||||
GetRelaunchRule()->SetLastWeaponUse(false);
|
||||
|
||||
//make lava collapse
|
||||
CreateObjectAbove(Firestone,625,480);
|
||||
|
@ -147,31 +148,9 @@ global func CreateChestContents(id obj_id)
|
|||
return;
|
||||
}
|
||||
|
||||
protected func InitializePlayer(int plr)
|
||||
public func RelaunchPosition()
|
||||
{
|
||||
return JoinPlayer(plr);
|
||||
}
|
||||
|
||||
// GameCall from RelaunchContainer.
|
||||
protected func RelaunchPlayer(int plr)
|
||||
{
|
||||
var clonk = CreateObjectAbove(Clonk, 0, 0, plr);
|
||||
clonk->MakeCrewMember(plr);
|
||||
SetCursor(plr, clonk);
|
||||
JoinPlayer(plr);
|
||||
return;
|
||||
}
|
||||
|
||||
protected func JoinPlayer(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
clonk->DoEnergy(100000);
|
||||
var position = [[420,200],[300,440],[130,176],[140,368],[700,192],[670,336],[750,440],[440,392],[45,256]];
|
||||
var r=Random(GetLength(position));
|
||||
var x = position[r][0], y = position[r][1];
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, x, y, clonk->GetOwner());
|
||||
relaunch->StartRelaunch(clonk);
|
||||
return;
|
||||
return [[420,200],[300,440],[130,176],[140,368],[700,192],[670,336],[750,440],[440,392],[45,256]];
|
||||
}
|
||||
|
||||
func RelaunchWeaponList() { return [Bow, Shield, Sword, Javelin, Blunderbuss, Club]; }
|
||||
|
|
|
@ -14,6 +14,7 @@ protected func Initialize()
|
|||
CreateObject(Goal_LastManStanding);
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_Gravestones);
|
||||
GetRelaunchRule()->SetLastWeaponUse(false);
|
||||
|
||||
//Enviroment.
|
||||
Cloud->Place(25);
|
||||
|
@ -339,27 +340,19 @@ global func CreateChestContents(id obj_id)
|
|||
// GameCall from RelaunchContainer.
|
||||
func OnClonkLeftRelaunch(object clonk)
|
||||
{
|
||||
var pos = GetRandomSpawn();
|
||||
clonk->SetPosition(pos[0],pos[1]);
|
||||
CreateParticle("Air", pos[0],pos[1], PV_Random(-20, 20), PV_Random(-20, 20), PV_Random(5, 10), Overcast_air_particles, 25);
|
||||
CreateParticle("Air", clonk->GetX(),clonk->GetY(), PV_Random(-20, 20), PV_Random(-20, 20), PV_Random(5, 10), Overcast_air_particles, 25);
|
||||
return;
|
||||
}
|
||||
|
||||
public func RelaunchPosition()
|
||||
{
|
||||
return [[432,270],[136,382],[200,134],[864,190],[856,382],[840,518],[408,86],[536,470]];
|
||||
|
||||
}
|
||||
|
||||
global func GetRandomSpawn()
|
||||
{
|
||||
var spawns = [[432,270],[136,382],[200,134],[864,190],[856,382],[840,518],[408,86],[536,470]];
|
||||
var rand = Random(GetLength(spawns));
|
||||
return spawns[rand];
|
||||
}
|
||||
|
||||
|
||||
// Gamecall from LastManStanding goal, on respawning.
|
||||
protected func OnPlayerRelaunch(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, LandscapeWidth() / 2, LandscapeHeight() / 2, clonk->GetOwner());
|
||||
relaunch->StartRelaunch(clonk);
|
||||
return;
|
||||
return RandomElement(Scenario->RelaunchPosition());
|
||||
}
|
||||
|
||||
func KillsToRelaunch() { return 0; }
|
||||
|
|
|
@ -12,6 +12,7 @@ protected func Initialize()
|
|||
CreateObject(Goal_LastManStanding, 0, 0, NO_OWNER);
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_Gravestones);
|
||||
GetRelaunchRule()->SetLastWeaponUse(false);
|
||||
|
||||
// Chests with weapons.
|
||||
var chest = CreateObjectAbove(Chest, 108, 248);
|
||||
|
@ -82,16 +83,6 @@ protected func InitializePlayer(int plr)
|
|||
return;
|
||||
}
|
||||
|
||||
// Gamecall from LastManStanding goal, on respawning.
|
||||
protected func OnPlayerRelaunch(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, LandscapeWidth() / 2, LandscapeHeight() / 2, clonk->GetOwner());
|
||||
relaunch->StartRelaunch(clonk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Refill/fill chests.
|
||||
global func FxIntFillChestsStart(object target, proplist effect, int temporary, object chest)
|
||||
{
|
||||
|
@ -135,5 +126,10 @@ public func OnClonkLeftRelaunch(object clonk)
|
|||
return;
|
||||
}
|
||||
|
||||
public func RelaunchPosition()
|
||||
{
|
||||
return [LandscapeWidth() / 2, LandscapeHeight() / 2];
|
||||
}
|
||||
|
||||
public func KillsToRelaunch() { return 0; }
|
||||
public func RelaunchWeaponList() { return [Bow, Shield, Sword, Firestone, Dynamite, Javelin, Blunderbuss]; }
|
||||
|
|
|
@ -13,6 +13,7 @@ protected func Initialize()
|
|||
CreateObject(Goal_LastManStanding, 0, 0, NO_OWNER);
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_Gravestones);
|
||||
GetRelaunchRule()->SetLastWeaponUse(false);
|
||||
|
||||
// Mood.
|
||||
SetSkyAdjust(RGBa(255, 255, 255, 127), RGB(255, 200, 150));
|
||||
|
@ -37,15 +38,6 @@ protected func Initialize()
|
|||
return;
|
||||
}
|
||||
|
||||
// Gamecall from LastManStanding goal, on respawning.
|
||||
protected func OnPlayerRelaunch(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, LandscapeWidth() / 2, LandscapeHeight() / 2, clonk->GetOwner());
|
||||
relaunch->StartRelaunch(clonk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
global func FxRainTimer(object pTarget, effect, int timer)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,9 @@ protected func Initialize()
|
|||
CreateObject(Goal_LastManStanding);
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_Gravestones);
|
||||
GetRelaunchRule()
|
||||
->SetRespawnDelay(3)
|
||||
->SetLastWeaponUse(false);
|
||||
|
||||
// Enviroment.
|
||||
CreateObject(Rule_ObjectFade)->DoFadeTime(10 * 36);
|
||||
|
@ -73,25 +76,21 @@ private func PlaceGras()
|
|||
return;
|
||||
}
|
||||
|
||||
protected func OnPlayerRelaunch(int plr)
|
||||
public func RelaunchPosition()
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
clonk->DoEnergy(100000);
|
||||
var x = RandomX(75,500);
|
||||
var y=100;
|
||||
while(!GBackSolid(x,y)) y+=1;
|
||||
y-=30;
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, x, y, clonk->GetOwner());
|
||||
relaunch->StartRelaunch(clonk);
|
||||
relaunch->SetRelaunchTime(3);
|
||||
clonk->CreateContents(TeleGlove);
|
||||
return;
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
public func OnClonkLeftRelaunch(object clonk)
|
||||
{
|
||||
clonk->CreateParticle("Fire", 0, 0, PV_Random(-20, 20), PV_Random(-40, 5), PV_Random(20, 90), Particles_Glimmer(), 30);
|
||||
clonk->SetYDir(-5);
|
||||
clonk->CreateContents(TeleGlove);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -104,5 +103,4 @@ public func OnClonkDeath(object clonk)
|
|||
}
|
||||
|
||||
// Settings for LMS and DM.
|
||||
public func RelaunchCount() { return 5; }
|
||||
public func WinKillCount() { return 5; }
|
||||
|
|
|
@ -18,6 +18,9 @@ protected func Initialize()
|
|||
AddEffect("BlessTheKing",goal,100,1,nil);
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_Gravestones);
|
||||
GetRelaunchRule()
|
||||
->SetLastWeaponUse(false)
|
||||
->SetDefaultRelaunchCount(nil);
|
||||
|
||||
//Enviroment.
|
||||
//SetSkyAdjust(RGBa(250,250,255,128),RGB(200,200,220));
|
||||
|
@ -247,29 +250,11 @@ protected func InitializePlayer(int plr)
|
|||
{
|
||||
// This scenario does not have shadows.
|
||||
SetFoW(false, plr);
|
||||
return JoinPlayer(plr);
|
||||
}
|
||||
|
||||
// GameCall from RelaunchContainer.
|
||||
protected func RelaunchPlayer(int plr)
|
||||
public func RelaunchPosition()
|
||||
{
|
||||
var clonk = CreateObjectAbove(Clonk, 0, 0, plr);
|
||||
clonk->MakeCrewMember(plr);
|
||||
SetCursor(plr, clonk);
|
||||
JoinPlayer(plr);
|
||||
return;
|
||||
}
|
||||
|
||||
protected func JoinPlayer(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
clonk->DoEnergy(100000);
|
||||
var position = [[180,150],[310,320],[600,290],[650,180],[790,110],[440,190]];
|
||||
var r=Random(GetLength(position));
|
||||
var x = position[r][0], y = position[r][1];
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, x, y + 49, clonk->GetOwner());
|
||||
relaunch->StartRelaunch(clonk);
|
||||
return;
|
||||
return [[180,150],[310,300],[600,290],[650,180],[790,110],[440,190]];
|
||||
}
|
||||
|
||||
func KillsToRelaunch() { return 0; }
|
||||
|
|
|
@ -18,6 +18,7 @@ public func SaveScenarioObject(props)
|
|||
var pos = GetHandlePosition();
|
||||
if (pos) props->AddCall("Handle", this, "SetSwitchDir", (pos>0)-(pos<0));
|
||||
}
|
||||
if (left_action || right_action) props->AddCall("Action", this, "SetActions", left_action, right_action);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -27,6 +28,13 @@ public func SetTarget(object trg)
|
|||
return true;
|
||||
}
|
||||
|
||||
public func SetActions(new_left_action, new_right_action)
|
||||
{
|
||||
left_action = new_left_action;
|
||||
right_action = new_right_action;
|
||||
return true;
|
||||
}
|
||||
|
||||
public func ConnectNearestDoor()
|
||||
{
|
||||
// EditCursor helper command: Connect to nearest door. Return connected door.
|
||||
|
@ -65,7 +73,7 @@ public func ControlRight(object clonk)
|
|||
|
||||
private func ControlSwitchDir(object clonk, int dir)
|
||||
{
|
||||
if (!target || !handle)
|
||||
if (!handle || (!target && !right_action && !left_action))
|
||||
{
|
||||
Sound("Structures::SwitchStuck");
|
||||
Message("$MsgStuck$");
|
||||
|
@ -120,7 +128,11 @@ public func SetR(int to_r)
|
|||
|
||||
private func SwitchingTimer(int dir)
|
||||
{
|
||||
if (!handle || !target) { Sound("Structures::SwitchStuck"); return SetAction("Idle"); }
|
||||
if (!handle || (!target && !right_action && !left_action))
|
||||
{
|
||||
Sound("Structures::SwitchStuck");
|
||||
return SetAction("Idle");
|
||||
}
|
||||
var handle_pos = GetHandlePosition();
|
||||
var handle_pos_new = BoundBy(handle_pos + HandleSpeed * dir, -MaxHandleAngle, +MaxHandleAngle);
|
||||
if (!handle_pos_new) handle_pos_new = dir; // avoid direct central position, so player cannot force the same direction twice
|
||||
|
@ -139,10 +151,11 @@ private func SwitchingTimer(int dir)
|
|||
private func DoSwitchFlip(object clonk, int dir)
|
||||
{
|
||||
// Perform action associated to this switch
|
||||
if (target)
|
||||
if (dir>0)
|
||||
if (dir > 0)
|
||||
{
|
||||
// Open/close should be aligned to vertical component of direction
|
||||
if (target)
|
||||
{
|
||||
// Open/close should be aligned to vertical component of direction
|
||||
if (GetR() < 0)
|
||||
{
|
||||
target->~OpenDoor(this);
|
||||
|
@ -151,12 +164,16 @@ private func DoSwitchFlip(object clonk, int dir)
|
|||
{
|
||||
target->~CloseDoor(this);
|
||||
}
|
||||
// Action last; it may delete the door/clonk/etc.
|
||||
}
|
||||
// Action last; it may delete the door/clonk/etc.
|
||||
if (right_action)
|
||||
UserAction->EvaluateAction(right_action, this, clonk);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open/close should be aligned to vertical component of direction
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open/close should be aligned to vertical component of direction
|
||||
if (target)
|
||||
{
|
||||
if (GetR() < 0)
|
||||
{
|
||||
target->~CloseDoor(this);
|
||||
|
@ -165,8 +182,11 @@ private func DoSwitchFlip(object clonk, int dir)
|
|||
{
|
||||
target->~OpenDoor(this);
|
||||
}
|
||||
UserAction->EvaluateAction(left_action, this, clonk);
|
||||
}
|
||||
// Action last; it may delete the door/clonk/etc.
|
||||
if (left_action)
|
||||
UserAction->EvaluateAction(left_action, this, clonk);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
[DefCore]
|
||||
id=Deco_TunnelSupport
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=30
|
||||
Height=30
|
||||
Offset=-15,-15
|
|
@ -0,0 +1,21 @@
|
|||
material TunnelSupport
|
||||
{
|
||||
receive_shadows on
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
ambient 1.0 1.0 1.0 1.0
|
||||
diffuse 0.800000011920929 0.800000011920929 0.800000011920929 1.0
|
||||
specular 0.2638509273529053 0.2638509273529053 0.2638509273529053 1.0 5.0
|
||||
emissive 0.0 0.0 0.0 1.0
|
||||
|
||||
texture_unit
|
||||
{
|
||||
texture TunnelSupport.png
|
||||
tex_address_mode wrap
|
||||
filtering trilinear
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
Tunnel support
|
||||
Purely for decoration
|
||||
|
||||
@authors: Clonkonaut, Ringwaul (Graphics)
|
||||
*/
|
||||
|
||||
local extension = 0;
|
||||
|
||||
func Construction()
|
||||
{
|
||||
SetProperty("MeshTransformation", Trans_Rotate(RandomX(75, 105), 0,1,0));
|
||||
}
|
||||
|
||||
// Stretch the support beams
|
||||
// 0 equals standard height (~30 pixels)
|
||||
// 100 is about 85 pixels
|
||||
public func Extend(int percentage)
|
||||
{
|
||||
percentage = BoundBy(percentage, 0, 100);
|
||||
|
||||
extension = percentage;
|
||||
|
||||
var height = 30 + (55 * percentage / 100);
|
||||
percentage = 2500 * percentage / 100;
|
||||
PlayAnimation("extend", 1, Anim_Const(percentage));
|
||||
|
||||
SetShape(-15, -15 + (30 - height), 30, height);
|
||||
}
|
||||
|
||||
public func SaveScenarioObject(props)
|
||||
{
|
||||
if (!inherited(props, ...))
|
||||
return false;
|
||||
|
||||
props->AddCall("Extension", this, "Extend", extension);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Plane = 701;
|
|
@ -0,0 +1 @@
|
|||
Name=Tunnelstütze
|
|
@ -0,0 +1 @@
|
|||
Name=Tunnel support
|
After Width: | Height: | Size: 84 KiB |
|
@ -46,7 +46,7 @@ func InitializePlayer(int plr, int iX, int iY, object pBase, int iTeam)
|
|||
{
|
||||
g_relaunchs = [];
|
||||
g_scores = [];
|
||||
Scoreboard->Init([{key = "relaunchs", title = Rule_Restart, sorted = true, desc = true, default = "", priority = 75},
|
||||
Scoreboard->Init([{key = "relaunchs", title = Rule_Relaunch, sorted = true, desc = true, default = "", priority = 75},
|
||||
{key = "score", title = Nugget, sorted = true, desc = true, default = "0", priority = 100}]);
|
||||
}
|
||||
for (var stonedoor in FindObjects(Find_ID(StoneDoor), Find_Owner(NO_OWNER))) stonedoor->SetOwner(plr);
|
||||
|
|
|
@ -15,7 +15,11 @@ protected func Initialize()
|
|||
|
||||
// Rules.
|
||||
CreateObject(Rule_BuyAtFlagpole);
|
||||
CreateObject(Rule_BaseRespawn);
|
||||
var relaunch_rule = GetRelaunchRule();
|
||||
relaunch_rule->SetBaseRespawn(true);
|
||||
relaunch_rule->SetFreeCrew(false);
|
||||
relaunch_rule->SetLastClonkRespawn(true);
|
||||
relaunch_rule->SetInitialRelaunch(false);
|
||||
CreateObject(Rule_TeamAccount);
|
||||
CreateObject(Rule_NoFriendlyFire);
|
||||
CreateObject(Rule_Gravestones)->SetFadeOut(3 * 36);
|
||||
|
|
|
@ -45,7 +45,7 @@ func InitializePlayer(int plr, int iX, int iY, object pBase, int iTeam)
|
|||
{
|
||||
g_relaunchs = [];
|
||||
g_scores = [];
|
||||
Scoreboard->Init([{key = "relaunchs", title = Rule_Restart, sorted = true, desc = true, default = "", priority = 75},
|
||||
Scoreboard->Init([{key = "relaunchs", title = Rule_Relaunch, sorted = true, desc = true, default = "", priority = 75},
|
||||
{key = "score", title = Nugget, sorted = true, desc = true, default = "0", priority = 100}]);
|
||||
}
|
||||
g_relaunchs[plr] = MAX_RELAUNCH;
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
[DefCore]
|
||||
id=Hatch
|
||||
Version=6,0
|
||||
Category=C4D_Structure
|
||||
Width=26
|
||||
Height=26
|
||||
Offset=-13,-13
|
||||
Vertices=5
|
||||
VertexX=0,-12,12,-10,10
|
||||
VertexY=0,0,0,6,6
|
||||
VertexFriction=100,100,100,100,100
|
||||
VertexCNAT=64,1,2,1,2
|
||||
SolidMask=0,0,20,20,0,0
|
||||
Construction=1
|
||||
Mass=10
|
Before Width: | Height: | Size: 272 B |
|
@ -1,7 +0,0 @@
|
|||
[DefCore]
|
||||
id=Hatch_Graphic
|
||||
Version=6,0
|
||||
Width=26
|
||||
Height=26
|
||||
Offset=-13,-13
|
||||
Category=C4D_Structure
|
|
@ -1,45 +0,0 @@
|
|||
//Hatch Graphic
|
||||
|
||||
local hatch_anim;
|
||||
local parent;
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
SetProperty("MeshTransformation", Trans_Mul(Trans_Translate(0,-10000), Trans_Rotate(-10,0,1,0), Trans_Rotate(-8,1,0,0)));
|
||||
}
|
||||
|
||||
public func SetHatchParent(object hatch)
|
||||
{
|
||||
parent = hatch;
|
||||
}
|
||||
|
||||
func Anim(string anim_name)
|
||||
{
|
||||
var animstart = 0;
|
||||
if(hatch_anim)
|
||||
{
|
||||
if(GetAnimationPosition(hatch_anim) != GetAnimationLength(anim_name))
|
||||
{
|
||||
animstart = GetAnimationLength(anim_name) - GetAnimationPosition(hatch_anim);
|
||||
}
|
||||
}
|
||||
|
||||
StopAnimation(hatch_anim);
|
||||
hatch_anim = PlayAnimation(anim_name, 5, Anim_Linear(animstart, 0, GetAnimationLength(anim_name), 14, ANIM_Hold));
|
||||
}
|
||||
|
||||
local ActMap = {
|
||||
Attach = {
|
||||
Prototype = Action,
|
||||
Name = "Attach",
|
||||
Procedure = DFA_ATTACH,
|
||||
Directions = 1,
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Wdt = 26,
|
||||
Hgt = 26,
|
||||
NextAction = "Attach",
|
||||
},
|
||||
};
|
||||
|
||||
local Plane = 100;
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
Hatch
|
||||
Author: Ringwaul
|
||||
*/
|
||||
|
||||
local graphic;
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
SetAction("Hatch");
|
||||
graphic = CreateObjectAbove(Hatch_Graphic);
|
||||
graphic->SetAction("Attach", this);
|
||||
graphic->SetHatchParent(this);
|
||||
return 1;
|
||||
}
|
||||
|
||||
func ControlUp(object clonk)
|
||||
{
|
||||
if(GetPhase() != 0)
|
||||
{
|
||||
graphic->Anim("Close");
|
||||
SetPhase(0);
|
||||
SetSolidMask(0,0,26,26,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
func ControlDown(object clonk)
|
||||
{
|
||||
if(GetPhase() != 1)
|
||||
{
|
||||
graphic->Anim("Open");
|
||||
SetPhase(1);
|
||||
SetSolidMask(26,0,26,26,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
protected func Definition(def)
|
||||
{
|
||||
SetProperty("PictureTransformation", Trans_Mul(Trans_Translate(0,-3000,-5000), Trans_Rotate(-30,1,0,0), Trans_Rotate(30,0,1,0), Trans_Translate(1000,1,0)),def);
|
||||
}
|
||||
|
||||
local Name = "$Name$";
|
||||
local Touchable = 2;
|
||||
local ActMap = {
|
||||
Hatch = {
|
||||
Prototype = Action,
|
||||
Name = "Hatch",
|
||||
Procedure = DFA_NONE,
|
||||
Directions = 1,
|
||||
FlipDir = 0,
|
||||
Length = 2,
|
||||
Delay = 0,
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Wdt = 1,
|
||||
Hgt = 1,
|
||||
},
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
Name=Hatch
|
|
@ -1 +0,0 @@
|
|||
Name=Hatch
|
|
@ -9,14 +9,8 @@ func InitializeObjects()
|
|||
var BoilingLava001 = CreateObject(BoilingLava);
|
||||
BoilingLava001->SetIntensity(25);
|
||||
|
||||
var Rule_BaseRespawn001 = CreateObject(Rule_BaseRespawn);
|
||||
Rule_BaseRespawn001->SetInventoryTransfer(true);
|
||||
Rule_BaseRespawn001->SetFreeCrew(true);
|
||||
|
||||
CreateObject(Rule_TeamAccount);
|
||||
|
||||
CreateObject(Rule_Restart);
|
||||
|
||||
CreateObjectAbove(Tree_Coniferous, 380, 877);
|
||||
|
||||
var Tree_Coniferous2001 = CreateObjectAbove(Tree_Coniferous2, 562, 563);
|
||||
|
|
|
@ -53,6 +53,14 @@ func DoInit(int first_player)
|
|||
// Start intro if not yet started
|
||||
StartSequence("Intro", 0, GetCrew(first_player));
|
||||
|
||||
GetRelaunchRule()
|
||||
->SetInventoryTransfer(true)
|
||||
->SetLastClonkRespawn(true)
|
||||
->SetFreeCrew(true)
|
||||
->SetAllowPlayerRestart(true)
|
||||
->SetBaseRespawn(true)
|
||||
->SetRespawnDelay(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,6 @@ func InitializeObjects()
|
|||
var Grass003 = CreateObjectAbove(Grass, 228, 1180);
|
||||
Grass003->SetClrModulation(0xffa08060);
|
||||
|
||||
var Rule_BaseRespawn001 = CreateObject(Rule_BaseRespawn);
|
||||
Rule_BaseRespawn001->SetInventoryTransfer(true);
|
||||
Rule_BaseRespawn001->SetFreeCrew(true);
|
||||
|
||||
var Tree_Coniferous_Burned001 = CreateObject(Tree_Coniferous_Burned, 17, 1097);
|
||||
Tree_Coniferous_Burned001->SetR(10);
|
||||
|
@ -543,7 +540,5 @@ func InitializeObjects()
|
|||
|
||||
CreateObject(Rule_Gravestones);
|
||||
|
||||
CreateObject(Rule_Restart);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ Definition1=Objects.ocd
|
|||
Definition2=Decoration.ocd
|
||||
|
||||
[Game]
|
||||
Rules=Rule_TeamAccount=1;Rule_NoPowerNeed=1;Rule_BaseRespawn=1;
|
||||
Rules=Rule_TeamAccount=1;Rule_NoPowerNeed=1;
|
||||
|
||||
[Player1]
|
||||
Knowledge=ToolsWorkshop=1;Foundry=1;Flagpole=1;Elevator=1;Armory=1;ChemicalLab=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;Bucket=1;Sword=1;Metal=1;GoldBar=1;Balloon=1;Boompack=1;GrappleBow=1;JarOfWinds=1;Pipe=1;Pump=1;PowderKeg=1;Ropeladder=1;Bow=1;Arrow=1;Club=1;IronBomb=1;Javelin=1;Shield=1;InventorsLab=1;Sawmill=1;BombArrow=1;FireArrow=1;GrenadeLauncher=1;Torch=1;WoodenBridge=1;Basement=1;
|
||||
|
|
|
@ -11,6 +11,15 @@ static npc_pyrit;
|
|||
|
||||
private func DoInit(int first_player)
|
||||
{
|
||||
var relaunch_rule = GetRelaunchRule();
|
||||
relaunch_rule->SetInventoryTransfer(true);
|
||||
relaunch_rule->SetFreeCrew(true);
|
||||
relaunch_rule->SetRespawnDelay(1);
|
||||
relaunch_rule->SetBaseRespawn(true);
|
||||
relaunch_rule->SetDefaultRelaunchCount(nil);
|
||||
relaunch_rule->SetAllowPlayerRestart(true);
|
||||
relaunch_rule->SetLastClonkRespawn(true);
|
||||
relaunch_rule->SetInitialRelaunch(false);
|
||||
// Message when first player enters shroom area
|
||||
ScheduleCall(nil, Scenario.ShroomCaveCheck, 21, 0xffffff);
|
||||
// Scorching village
|
||||
|
@ -115,4 +124,4 @@ public func OnGoalsFulfilled()
|
|||
GainScenarioAchievement("Done");
|
||||
GainMissionAccess("S2Castle");
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ MsgEncounterCave=Ein Eindringling klaut unser Gold! Schnappt ihn!
|
|||
MsgEncounterOutpost=Halt, im Namen des Königs!
|
||||
MsgEncounterKing=Ah, %s. Ich habe Euch bereits erwartet.
|
||||
MsgEncounterShrooms=Was ist steht denn da Feines in dieser Höhle? Vielleicht kommen wir damit ja ins Schloss hinein.
|
||||
NameHorax=Horax
|
||||
NameHorax=Hörx
|
||||
DeathOfHorst=Er hinterlässt Frau und zwei Kinder.
|
||||
DeathOfHanniball=Sein Lachen wird vermisst werden.
|
||||
DeathOfTwonky=Ein vielversprechender, junger Filmstar.
|
||||
|
|
|
@ -2,7 +2,7 @@ MsgEncounterCave=An intruder tries to steal our gold. Catch him!
|
|||
MsgEncounterOutpost=Stop, in the name of the king!
|
||||
MsgEncounterKing=Ah, %s. I have been awaiting you.
|
||||
MsgEncounterShrooms=What is this in the cave? Fireworks? Maybe we can use them to get into the castle.
|
||||
NameHorax=Hörx
|
||||
NameHorax=Harx
|
||||
DeathOfHorst=He left a wife and two children.
|
||||
DeathOfHanniball=His laughter will be missed.
|
||||
DeathOfTwonky=A promising young movie star.
|
||||
|
|
|
@ -11,7 +11,7 @@ Definition2=Decoration.ocd\Misc.ocd\Hat.ocd
|
|||
Definition3=Decoration.ocd\Clonk.ocd\AltSkins.ocd
|
||||
|
||||
[Game]
|
||||
Rules=Rule_TeamAccount=1;Rule_BuyAtFlagpole=1;Rule_BaseRespawn=1;Rule_Restart=1;
|
||||
Rules=Rule_TeamAccount=1;Rule_BuyAtFlagpole=1;
|
||||
Goals=Goal_BuildCrystalCommunicator=1;
|
||||
ValueOverloads=Ruby=10;Amethyst=10
|
||||
|
||||
|
|
|
@ -33,12 +33,15 @@ protected func PostIntroInitialize()
|
|||
}
|
||||
|
||||
// Rules
|
||||
var respawn_rule = FindObject(Find_ID(Rule_BaseRespawn));
|
||||
if (respawn_rule)
|
||||
{
|
||||
respawn_rule->SetInventoryTransfer(true);
|
||||
respawn_rule->SetFreeCrew(true);
|
||||
}
|
||||
var relaunch_rule = GetRelaunchRule();
|
||||
relaunch_rule->SetInventoryTransfer(true);
|
||||
relaunch_rule->SetFreeCrew(true);
|
||||
relaunch_rule->SetRespawnDelay(1);
|
||||
relaunch_rule->SetBaseRespawn(true);
|
||||
relaunch_rule->SetDefaultRelaunchCount(nil);
|
||||
relaunch_rule->SetAllowPlayerRestart(true);
|
||||
relaunch_rule->SetLastClonkRespawn(true);
|
||||
relaunch_rule->SetInitialRelaunch(false);
|
||||
|
||||
// Initialize different parts of the scenario.
|
||||
InitializeAmbience();
|
||||
|
@ -311,4 +314,4 @@ global func Particles_Smoke(...)
|
|||
p.DampingX = 800;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,14 @@ func Initialize()
|
|||
if (loc = FindLocation(Loc_InRect(0,80*8,40*8,20*8), Loc_Material("Earth")))
|
||||
CreateObjectAbove(Rock, loc.x, loc.y+3);
|
||||
SetSkyParallax(1, 20,20, 0,0, nil, nil);
|
||||
var relaunch_rule = GetRelaunchRule();
|
||||
relaunch_rule->SetInventoryTransfer(true);
|
||||
relaunch_rule->SetFreeCrew(true);
|
||||
relaunch_rule->SetRespawnDelay(1);
|
||||
relaunch_rule->SetBaseRespawn(false);
|
||||
relaunch_rule->SetDefaultRelaunchCount(nil);
|
||||
relaunch_rule->SetAllowPlayerRestart(true);
|
||||
relaunch_rule->SetLastClonkRespawn(true);
|
||||
}
|
||||
|
||||
static g_was_player_init;
|
||||
|
@ -26,50 +34,52 @@ func InitializePlayer(int plr)
|
|||
InitBase(plr);
|
||||
g_was_player_init = true;
|
||||
}
|
||||
// Position and materials
|
||||
JoinPlayer(plr);
|
||||
// Position.
|
||||
var clonk = GetCrew(plr);
|
||||
var pos = RelaunchPosition();
|
||||
clonk->SetPosition(pos[0], pos[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
private func InitBase(int owner)
|
||||
{
|
||||
// Create standard base owned by player
|
||||
var y=90*8, x=40*8;
|
||||
var flag = CreateObjectAbove(Flagpole, x+85,y, owner);
|
||||
var y = 90 * 8, x=40 * 8;
|
||||
CreateObjectAbove(Flagpole, x+85,y, owner);
|
||||
var hut = CreateObjectAbove(ToolsWorkshop, x+45,y, owner);
|
||||
if (hut)
|
||||
{
|
||||
hut->CreateContents(Shovel, 1);
|
||||
hut->CreateContents(Loam, 1);
|
||||
}
|
||||
for (var i=0; i<3; ++i) CreateObjectAbove(Boompack, x+20+i*5+Random(4),y, owner);
|
||||
for (var i = 0; i < 3; ++i)
|
||||
CreateObjectAbove(Boompack, x+20+i*5+Random(4),y, owner);
|
||||
return true;
|
||||
}
|
||||
|
||||
func RelaunchPlayer(int plr)
|
||||
public func RelaunchPlayer(int plr)
|
||||
{
|
||||
var clonk = CreateObjectAbove(Clonk, 50, 1000, plr);
|
||||
clonk->MakeCrewMember(plr);
|
||||
SetCursor(plr, clonk);
|
||||
JoinPlayer(plr);
|
||||
return true;
|
||||
}
|
||||
|
||||
func JoinPlayer(int plr)
|
||||
public func OnPlayerRelaunch(int plr, bool is_relaunch)
|
||||
{
|
||||
var i, crew;
|
||||
for (i=0; crew=GetCrew(plr,i); ++i)
|
||||
if (!is_relaunch)
|
||||
{
|
||||
crew->SetPosition(40*8+Random(40), 90*8-10);
|
||||
if (!i)
|
||||
{
|
||||
crew->CreateContents(GrappleBow, 2);
|
||||
crew->CreateContents(WindBag);
|
||||
crew->CreateContents(TeleGlove);
|
||||
crew->CreateContents(Dynamite, 2);
|
||||
}
|
||||
var clonk = GetCrew(plr);
|
||||
clonk->CreateContents(GrappleBow, 2);
|
||||
clonk->CreateContents(WindBag);
|
||||
clonk->CreateContents(TeleGlove);
|
||||
clonk->CreateContents(Dynamite, 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public func RelaunchPosition()
|
||||
{
|
||||
return [40 * 8 + Random(40), 90 * 8 - 10];
|
||||
}
|
||||
|
||||
func OnGoalsFulfilled()
|
||||
|
|
|
@ -7,17 +7,11 @@ func InitializeObjects()
|
|||
var Time001 = CreateObject(Time);
|
||||
Time001->SetTime(600);
|
||||
Time001->SetCycleSpeed(20);
|
||||
|
||||
var Rule_BaseRespawn001 = CreateObject(Rule_BaseRespawn);
|
||||
Rule_BaseRespawn001->SetInventoryTransfer(true);
|
||||
Rule_BaseRespawn001->SetFreeCrew(true);
|
||||
|
||||
CreateObject(Rule_NoPowerNeed);
|
||||
|
||||
CreateObject(Rule_TeamAccount);
|
||||
|
||||
CreateObject(Rule_Restart);
|
||||
|
||||
CreateObjectAbove(EnvPack_Scarecrow, 1218, 440);
|
||||
|
||||
CreateObjectAbove(EnvPack_Guidepost, 835, 369);
|
||||
|
|
|
@ -10,7 +10,7 @@ Definition2=Decoration.ocd
|
|||
|
||||
[Game]
|
||||
Goals=Goal_Raid=1
|
||||
Rules=Rule_TeamAccount=1;Rule_NoPowerNeed=1;Rule_BaseRespawn=1;
|
||||
Rules=Rule_TeamAccount=1;Rule_NoPowerNeed=1;
|
||||
|
||||
[Player1]
|
||||
Knowledge=Foundry=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;ChemicalLab=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;Bucket=1;GoldBar=1;Metal=1;Pipe=1;WallKit=1;WindGenerator=1;
|
||||
|
|
|
@ -26,6 +26,15 @@ static g_is_initialized, // intro started
|
|||
|
||||
func Initialize()
|
||||
{
|
||||
var relaunch_rule = GetRelaunchRule();
|
||||
relaunch_rule->SetInventoryTransfer(true);
|
||||
relaunch_rule->SetFreeCrew(true);
|
||||
relaunch_rule->SetRespawnDelay(1);
|
||||
relaunch_rule->SetBaseRespawn(true);
|
||||
relaunch_rule->SetDefaultRelaunchCount(nil);
|
||||
relaunch_rule->SetAllowPlayerRestart(true);
|
||||
relaunch_rule->SetLastClonkRespawn(true);
|
||||
relaunch_rule->SetInitialRelaunch(false);
|
||||
npc_newton->SetAlternativeSkin("MaleBlackHair");
|
||||
npc_pyrit->SetAlternativeSkin("MaleBrownHair");
|
||||
npc_woody->SetAlternativeSkin("Youngster");
|
||||
|
|
|
@ -32,16 +32,10 @@ func InitializeObjects()
|
|||
Column001->SetMeshMaterial("AncientColumn", 0);
|
||||
Column001.Plane = 50;
|
||||
|
||||
var Rule_BaseRespawn001 = CreateObject(Rule_BaseRespawn);
|
||||
Rule_BaseRespawn001->SetInventoryTransfer(true);
|
||||
Rule_BaseRespawn001->SetFreeCrew(true);
|
||||
|
||||
CreateObject(Rule_TeamAccount);
|
||||
|
||||
CreateObject(Rule_NoPowerNeed);
|
||||
|
||||
CreateObject(Rule_Restart);
|
||||
|
||||
var LargeCaveMushroom001 = CreateObjectAbove(LargeCaveMushroom, 1308, 1038);
|
||||
LargeCaveMushroom001->SetClrModulation(0xffe4effc);
|
||||
var LargeCaveMushroom002 = CreateObjectAbove(LargeCaveMushroom, 1345, 1028);
|
||||
|
|
|
@ -10,7 +10,7 @@ MissionAccess=S2Sea
|
|||
Definition2=Decoration.ocd
|
||||
|
||||
[Game]
|
||||
Rules=Rule_TeamAccount=1;Rule_NoPowerNeed=1;Rule_BaseRespawn=1;
|
||||
Rules=Rule_TeamAccount=1;Rule_NoPowerNeed=1;
|
||||
|
||||
[Player1]
|
||||
Knowledge=ToolsWorkshop=1;Foundry=1;Flagpole=1;Elevator=1;Armory=1;ChemicalLab=1;Lorry=1;Pickaxe=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;Bucket=1;Sword=1;Metal=1;Balloon=1;Boompack=1;GrappleBow=1;JarOfWinds=1;Pipe=1;Pump=1;PowderKeg=1;Ropeladder=1;Bow=1;Arrow=1;Club=1;IronBomb=1;Javelin=1;Shield=1;Catapult=1;WallKit=1;WoodenBridge=1;Basement=1;
|
||||
|
|
|
@ -15,6 +15,15 @@ static npc_pyrit;
|
|||
|
||||
func DoInit(int first_player)
|
||||
{
|
||||
var relaunch_rule = GetRelaunchRule();
|
||||
relaunch_rule->SetInventoryTransfer(true);
|
||||
relaunch_rule->SetFreeCrew(true);
|
||||
relaunch_rule->SetRespawnDelay(1);
|
||||
relaunch_rule->SetBaseRespawn(true);
|
||||
relaunch_rule->SetDefaultRelaunchCount(nil);
|
||||
relaunch_rule->SetAllowPlayerRestart(true);
|
||||
relaunch_rule->SetLastClonkRespawn(true);
|
||||
relaunch_rule->SetInitialRelaunch(false);
|
||||
ClearFreeRect(530,1135, 50,2);
|
||||
if (g_last_stone_door) g_last_stone_door->DoDamage(170 - g_last_stone_door->GetDamage());
|
||||
if (g_golden_idol)
|
||||
|
@ -174,5 +183,4 @@ func OnInvincibleDamage(object damaged_target)
|
|||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
[DefCore]
|
||||
id=LavaCore
|
||||
Version=8,0
|
||||
Category=C4D_Living
|
||||
Height=40
|
||||
Width=40
|
||||
Offset=-20,-20
|
||||
Vertices=9
|
||||
VertexX=0,-19,19, 0, 0,-14, 14,-14,14
|
||||
VertexY=0, 0, 0,-19,19,-14,-14, 14,14
|
||||
VertexFriction=1,50,50,50,50,50,50,50,50
|
||||
VertexCNAT=16,1,2,4,8,5,6,9,10
|
||||
Mass=80
|
||||
StretchGrowth=1
|
||||
Oversize=1
|
||||
IncompleteActivity=1
|
||||
NoBreath=1
|
||||
Float=1
|
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 216 KiB |
|
@ -0,0 +1,14 @@
|
|||
[DefCore]
|
||||
id=LavaCoreShell
|
||||
Version=8,0
|
||||
Category=C4D_None
|
||||
Width=56
|
||||
Height=56
|
||||
Offset=-28,-28
|
||||
Vertices=1
|
||||
VertexX=0
|
||||
VertexY=0
|
||||
SolidMask=0,0,4,8,24,24
|
||||
Rotate=1
|
||||
NoStabilize=1
|
||||
HideInCreator=true
|
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 6.9 KiB |
|
@ -0,0 +1,54 @@
|
|||
material LavaShellMat
|
||||
{
|
||||
receive_shadows off
|
||||
|
||||
technique 0
|
||||
{
|
||||
pass 0
|
||||
{
|
||||
|
||||
|
||||
ambient 0.500000 0.500000 0.500000 1.000000
|
||||
diffuse 0.800000 0.316192 0.800000 1.000000
|
||||
specular 0.500000 0.500000 0.500000 1.000000 12.500000
|
||||
emissive 0.000000 0.000000 0.000000 1.000000
|
||||
scene_blend alpha_blend
|
||||
depth_write off
|
||||
|
||||
texture_unit
|
||||
{
|
||||
texture LavaCoreShell.png
|
||||
tex_address_mode wrap
|
||||
filtering trilinear
|
||||
colour_op_ex source1 src_texture src_texture
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
material LavaShellStoneMat
|
||||
{
|
||||
receive_shadows off
|
||||
|
||||
technique 0
|
||||
{
|
||||
pass 0
|
||||
{
|
||||
|
||||
|
||||
ambient 0.500000 0.500000 0.500000 1.000000
|
||||
diffuse 0.800000 0.316192 0.800000 1.000000
|
||||
specular 0.500000 0.500000 0.500000 1.000000 12.500000
|
||||
emissive 0.000000 0.000000 0.000000 1.000000
|
||||
scene_blend alpha_blend
|
||||
depth_write off
|
||||
|
||||
texture_unit
|
||||
{
|
||||
texture LavaCoreShellStone.png
|
||||
tex_address_mode wrap
|
||||
filtering trilinear
|
||||
colour_op_ex source1 src_texture src_texture
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
LavaCore Shell
|
||||
Protects the lava core and provides a solidmask for the clonk to walk on.
|
||||
|
||||
@author Win, Maikel
|
||||
*/
|
||||
|
||||
|
||||
local size;
|
||||
|
||||
public func InitAttach(object parent)
|
||||
{
|
||||
SetAction("Attach", parent);
|
||||
SetSize(BoundBy(parent->GetCon(), parent.SizeLimitMin, parent.SizeLimitMax));
|
||||
return;
|
||||
}
|
||||
|
||||
public func SetSize(int size)
|
||||
{
|
||||
// Rotate core to solidmask.
|
||||
var r = -70;
|
||||
var fsin = Sin(r, 10 * size), fcos = Cos(r, 10 * size);
|
||||
SetObjDrawTransform(+fcos, +fsin, 0, -fsin, +fcos, 0);
|
||||
// Update solid mask.
|
||||
var solid_size = 2 * ((size * 20 / 100 + 2) / 2) + 4;
|
||||
solid_size = BoundBy(solid_size, 4, 28);
|
||||
var solid_x = (1 + solid_size / 2) * (solid_size - 4);
|
||||
SetSolidMask(solid_x, 0, solid_size * 2, solid_size * 2, 28 - solid_size, 28 - solid_size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*-- Saving --*/
|
||||
|
||||
public func SaveScenarioObject() { return false; }
|
||||
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Plane = 425;
|
||||
|
||||
local ActMap = {
|
||||
Attach = {
|
||||
Prototype = Action,
|
||||
Name = "Attach",
|
||||
Procedure = DFA_ATTACH,
|
||||
Length = 1,
|
||||
Delay = 0,
|
||||
FacetBase = 1,
|
||||
NextAction = "Attach",
|
||||
}
|
||||
};
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1,2 @@
|
|||
Name=Lavacore Shell
|
||||
Description=Protects the lava core.
|
|
@ -0,0 +1,2 @@
|
|||
Name=Lavacore Shell
|
||||
Description=Protects the lava core.
|
After Width: | Height: | Size: 44 KiB |
|
@ -0,0 +1,63 @@
|
|||
material LavaCoreMat: NormalMap
|
||||
{
|
||||
receive_shadows off
|
||||
|
||||
technique 0
|
||||
{
|
||||
pass 0
|
||||
{
|
||||
cull_hardware none
|
||||
|
||||
ambient 0.500000 0.500000 0.500000 1.000000
|
||||
diffuse 1.000000 1.000000 1.000000 1.000000
|
||||
specular 0.500000 0.500000 0.500000 1.000000 12.500000
|
||||
scene_blend alpha_blend
|
||||
depth_write off
|
||||
|
||||
texture_unit base
|
||||
{
|
||||
texture LavaCore.png
|
||||
tex_address_mode wrap
|
||||
filtering trilinear
|
||||
}
|
||||
|
||||
texture_unit normal
|
||||
{
|
||||
texture LavaCoreNormals.png
|
||||
tex_address_mode wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
material LavaCoreStoneMat: NormalMap
|
||||
{
|
||||
receive_shadows off
|
||||
|
||||
technique 0
|
||||
{
|
||||
pass 0
|
||||
{
|
||||
cull_hardware none
|
||||
|
||||
ambient 0.500000 0.500000 0.500000 1.000000
|
||||
diffuse 1.000000 1.000000 1.000000 1.000000
|
||||
specular 0.500000 0.500000 0.500000 1.000000 12.500000
|
||||
scene_blend alpha_blend
|
||||
depth_write off
|
||||
|
||||
texture_unit base
|
||||
{
|
||||
texture LavaCoreStone.png
|
||||
tex_address_mode wrap
|
||||
filtering trilinear
|
||||
}
|
||||
|
||||
texture_unit normal
|
||||
{
|
||||
texture LavaCoreNormals.png
|
||||
tex_address_mode wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,420 @@
|
|||
/**
|
||||
LavaCore
|
||||
The lava high life. Moves rythmically, spews lava, acts as platform for clonks.
|
||||
|
||||
@author Win, Maikel
|
||||
*/
|
||||
|
||||
#include Library_Animal
|
||||
|
||||
|
||||
// The outer shell of the core.
|
||||
local shell;
|
||||
local fx_behavior;
|
||||
|
||||
|
||||
public func Construction()
|
||||
{
|
||||
shell = CreateObjectAbove(LavaCoreShell);
|
||||
shell->InitAttach(this);
|
||||
this.MaxSize = RandomX(40, 50);
|
||||
// Add a reproduction timer (from the animal library).
|
||||
AddReproductionEffect();
|
||||
// Add an effect to control the lava core.
|
||||
fx_behavior = CreateEffect(FxCoreBehavior, 100, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
public func Initialize()
|
||||
{
|
||||
if (shell)
|
||||
shell->SetSize(GetCon());
|
||||
return;
|
||||
}
|
||||
|
||||
public func Place(int amount, proplist rectangle, proplist settings)
|
||||
{
|
||||
var max_tries = 5 * amount;
|
||||
var loc_area = nil;
|
||||
if (rectangle) loc_area = Loc_InArea(rectangle);
|
||||
var size_range = nil;
|
||||
if (settings)
|
||||
size_range = settings.size_range;
|
||||
var cores = [];
|
||||
|
||||
while ((amount > 0) && (--max_tries > 0))
|
||||
{
|
||||
var spot = FindLocation(Loc_Material("Lava"), Loc_Space(20), loc_area);
|
||||
if(!Random(2))
|
||||
spot = FindLocation(Loc_Material("DuroLava"), Loc_Space(20), loc_area);
|
||||
if (!spot) continue;
|
||||
|
||||
var core = CreateObjectAbove(this, spot.x, spot.y, NO_OWNER);
|
||||
if (!core) continue;
|
||||
|
||||
if (settings.size_range)
|
||||
{
|
||||
var size = RandomX(settings.size_range[0], settings.size_range[1]);
|
||||
core.MaxSize = BoundBy(size, core.SizeLimitMin, core.SizeLimitMax);
|
||||
core->SetCon(core.MaxSize);
|
||||
}
|
||||
if (core->Stuck())
|
||||
{
|
||||
core->RemoveObject();
|
||||
continue;
|
||||
}
|
||||
--amount;
|
||||
PushBack(cores, core);
|
||||
}
|
||||
return cores;
|
||||
}
|
||||
|
||||
public func SetCon(int new_size)
|
||||
{
|
||||
if (shell)
|
||||
shell->SetSize(new_size);
|
||||
return _inherited(new_size, ...);
|
||||
}
|
||||
|
||||
public func DoCon(int add_size)
|
||||
{
|
||||
if (shell)
|
||||
shell->SetSize(GetCon() + add_size);
|
||||
return _inherited(add_size, ...);
|
||||
}
|
||||
|
||||
public func Destruction()
|
||||
{
|
||||
if (shell)
|
||||
shell->RemoveObject();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*-- Core Behaviour --*/
|
||||
|
||||
local FxCoreBehavior = new Effect
|
||||
{
|
||||
Construction = func()
|
||||
{
|
||||
this.fossilized = false;
|
||||
this.move_vector = [0, 0];
|
||||
this.movement_step = 72;
|
||||
this.frames_per_attack = 9;
|
||||
this.evading_core = 0;
|
||||
// Change time to have cores perform actions at different times.
|
||||
this.Time = Random(this.movement_step);
|
||||
// Make core swim and able to move.
|
||||
Target->SetAction("Swim");
|
||||
Target->SetComDir(COMD_None);
|
||||
return;
|
||||
},
|
||||
|
||||
Timer = func(int time)
|
||||
{
|
||||
// Check if fossilized and change state.
|
||||
this->CheckFossilized(time);
|
||||
if (this.fossilized)
|
||||
return FX_OK;
|
||||
|
||||
// Do growth.
|
||||
this->DoGrowth(time);
|
||||
|
||||
// Attack prey if possible.
|
||||
if ((time % this.frames_per_attack) == 0)
|
||||
this->AttackPrey(time);
|
||||
|
||||
// Do movement.
|
||||
this->DoMovement(time);
|
||||
|
||||
return FX_OK;
|
||||
},
|
||||
|
||||
CheckFossilized = func(int time)
|
||||
{
|
||||
if (this.fossilized && !Random(120))
|
||||
{
|
||||
Target->Revive();
|
||||
this.fossilized = false;
|
||||
}
|
||||
// Fossilize more ofen at surface.
|
||||
if (!this.fossilized && (!Random(160) || (!Random(100) && !Target->GBackLiquid(0, -6))))
|
||||
{
|
||||
Target->Fossilize();
|
||||
this.fossilized = true;
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
AttackPrey = func(int time)
|
||||
{
|
||||
// Only if fully grown and not fossilized.
|
||||
if (Target->GetCon() < Target.MaxSize || this.fossilized)
|
||||
return;
|
||||
|
||||
// Shoot a bubble at a nearby prey if the path is free, sometimes randomly shoot a bubble.
|
||||
var prey = Target->FindObject(Find_OCF(OCF_Alive), Target->Find_Distance(100), Target->Find_PathFree(), Find_Not(Find_ID(LavaCore)));
|
||||
if (!prey && Random(60))
|
||||
return;
|
||||
|
||||
var angle = Random(360);
|
||||
if (prey)
|
||||
angle = Angle(Target->GetX(), Target->GetY(), prey->GetX(), prey->GetY());
|
||||
var test_x = Sin(angle, Target->GetCon() / 4);
|
||||
var test_y = -Cos(angle, Target->GetCon() / 4);
|
||||
if (!PathFree(Target->GetX(), Target->GetY(), Target->GetX() + test_x, Target->GetY() + test_y))
|
||||
return;
|
||||
|
||||
var bubble = Target->CreateObject(BoilingLava_Bubble);
|
||||
bubble->SetVelocity(angle, RandomX(30, 40));
|
||||
bubble->DoCon(RandomX(10, 35));
|
||||
},
|
||||
|
||||
DoGrowth = func(int time)
|
||||
{
|
||||
if (Target->GetCon() >= Target.MaxSize)
|
||||
return;
|
||||
// Only grow in lava.
|
||||
var mat = MaterialName(Target->GetMaterial(0, 5));
|
||||
if (mat == "Lava" || mat == "DuroLava")
|
||||
if (Target->GetCon() < Target.MaxSize && !Random(45))
|
||||
Target->DoCon(1);
|
||||
return;
|
||||
},
|
||||
|
||||
DoMovement = func(int time)
|
||||
{
|
||||
// Only perform movement if swimming.
|
||||
if (Target->GetAction() != "Swim")
|
||||
return;
|
||||
|
||||
var forced = false;
|
||||
var speed = Target.MovementSpeed;
|
||||
|
||||
// Evade other cores. This will keep them evenly spread.
|
||||
var cnat = Target->GetContact(-1);
|
||||
if (!Target->InLiquid())
|
||||
{
|
||||
//Log("[%d]%v out of liquid", FrameCounter(), Target);
|
||||
cnat = cnat | CNAT_Top;
|
||||
}
|
||||
var other_core = Target->FindObject(Find_ID(LavaCore), Find_Exclude(Target), Target->Find_Distance(20 + Target.MaxSize));
|
||||
// Check for contact.
|
||||
if (cnat & (CNAT_Left | CNAT_Right | CNAT_Top | CNAT_Bottom) && this.evading_move <= 0)
|
||||
{
|
||||
this.move_vector = [RandomX(-1, 1), RandomX(-1, 1)];
|
||||
if ((cnat & CNAT_Left) && !(cnat & CNAT_Right))
|
||||
this.move_vector[0] = 1;
|
||||
if ((cnat & CNAT_Right) && !(cnat & CNAT_Left))
|
||||
this.move_vector[0] = -1;
|
||||
if ((cnat & CNAT_Top) && !(cnat & CNAT_Bottom))
|
||||
this.move_vector[1] = 1;
|
||||
if ((cnat & CNAT_Bottom) && !(cnat & CNAT_Top))
|
||||
this.move_vector[1] = -1;
|
||||
//Log("[%d]%v has contact: %d and move vector %v", FrameCounter(), Target, cnat, this.move_vector);
|
||||
this.evading_move = 6;
|
||||
forced = true;
|
||||
}
|
||||
// After contact is dealt with we can evade other cores.
|
||||
else if (other_core && this.evading_move <= 0)
|
||||
{
|
||||
//Log("[%d]other core", FrameCounter());
|
||||
this.move_vector[0] = Sign(Target->GetX() - other_core->GetX());
|
||||
this.move_vector[1] = Sign(Target->GetY() - other_core->GetY());
|
||||
this.evading_move = 16;
|
||||
forced = true;
|
||||
}
|
||||
// Otherwise just do random movement.
|
||||
else
|
||||
{
|
||||
this.move_vector[0] = RandomX(-1, 1);
|
||||
this.move_vector[1] = RandomX(-1, 1);
|
||||
// Move upwards more often to stay at surface more often.
|
||||
if (Random(3))
|
||||
this.move_vector[1] = -1;
|
||||
}
|
||||
|
||||
// Execute the movement.
|
||||
if ((time % this.movement_step) == 0 || forced)
|
||||
{
|
||||
Target->SetXDir(this.move_vector[0] * speed + RandomX(-speed, speed) / 10);
|
||||
Target->SetYDir(this.move_vector[1] * speed + RandomX(-speed, speed) / 10);
|
||||
}
|
||||
if ((time % this.movement_step) == 0 && Target.shell)
|
||||
Target.shell->SetRDir(5 * (2 * Random(2) - 1));
|
||||
|
||||
// Dampen movement over time to make movements seem like impulses.
|
||||
var xdir = Target->GetXDir(1000);
|
||||
var ydir = Target->GetYDir(1000);
|
||||
if (xdir > 0)
|
||||
Target->SetXDir(xdir - 3 * speed, 1000);
|
||||
else
|
||||
Target->SetXDir(xdir + 3 * speed, 1000);
|
||||
if (ydir > 0)
|
||||
Target->SetYDir(ydir - 3 * speed, 1000);
|
||||
else
|
||||
Target->SetYDir(ydir + 3 * speed, 1000);
|
||||
|
||||
this.evading_move--;
|
||||
return;
|
||||
},
|
||||
|
||||
IsFossilized = func()
|
||||
{
|
||||
return this.fossilized;
|
||||
}
|
||||
};
|
||||
|
||||
public func StartNonSwim()
|
||||
{
|
||||
if (GBackLiquid())
|
||||
{
|
||||
SetAction("Swim");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*-- Reproduction --*/
|
||||
|
||||
private func ReproductionCondition()
|
||||
{
|
||||
return GetAlive() && GetCon() >= this.MaxSize;
|
||||
}
|
||||
|
||||
private func SpecialReproductionCondition()
|
||||
{
|
||||
if (fx_behavior)
|
||||
return !fx_behavior->IsFossilized();
|
||||
return false;
|
||||
}
|
||||
|
||||
public func Birth(object parent)
|
||||
{
|
||||
SetCon(BoundBy(GetCon(), this.SizeLimitMin, this.SizeLimitMax));
|
||||
if (shell)
|
||||
shell->SetSize(GetCon());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*-- Core State --*/
|
||||
|
||||
// Explode on death.
|
||||
public func Death()
|
||||
{
|
||||
if (shell)
|
||||
shell->RemoveObject();
|
||||
|
||||
Explode(BoundBy(GetCon() / 2, 20, 90));
|
||||
return;
|
||||
}
|
||||
|
||||
// Turns the core into a fossil.
|
||||
public func Fossilize()
|
||||
{
|
||||
Sound("Animals::LavaCore::Fossilize", {volume = GetCon()});
|
||||
SetComDir(COMD_Stop);
|
||||
SetMeshMaterial("LavaCoreStoneMat");
|
||||
if (shell)
|
||||
{
|
||||
shell->SetMeshMaterial("LavaShellStoneMat");
|
||||
shell->SetRDir(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Turns the fossil into a core again.
|
||||
public func Revive()
|
||||
{
|
||||
SetAction("Swim");
|
||||
SetComDir(COMD_None);
|
||||
SetMeshMaterial("LavaCoreMat");
|
||||
if (shell)
|
||||
shell->SetMeshMaterial("LavaShellMat");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*-- Saving --*/
|
||||
|
||||
public func SaveScenarioObject(proplist props)
|
||||
{
|
||||
if (!inherited(props, ...))
|
||||
return false;
|
||||
// Avoid saving some stuff that's reinitialized anyway.
|
||||
props->Remove("MeshMaterial");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Plane = 424;
|
||||
local CorrosionResist = true;
|
||||
local MaxEnergy = 100000;
|
||||
local ContactCalls = true;
|
||||
local SizeLimitMin = 15; // Min size of all cores.
|
||||
local SizeLimitMax = 100; // Max size of all cores.
|
||||
local MaxSize = 50; // To which size this core will grow.
|
||||
local MovementSpeed = 20;
|
||||
|
||||
local ActMap = {
|
||||
Swim = {
|
||||
Prototype = Action,
|
||||
Name = "Swim",
|
||||
Procedure = DFA_SWIM,
|
||||
Speed = 100,
|
||||
Accel = 16,
|
||||
Decel = 16,
|
||||
Length = 1,
|
||||
Delay = 0,
|
||||
FacetBase = 1,
|
||||
NextAction = "Swim"
|
||||
},
|
||||
Walk = {
|
||||
Prototype = Action,
|
||||
Name = "Walk",
|
||||
Procedure = DFA_WALK,
|
||||
Speed = 100,
|
||||
Accel = 16,
|
||||
Decel = 16,
|
||||
Length = 1,
|
||||
Delay = 0,
|
||||
FacetBase = 1,
|
||||
NextAction = "Walk",
|
||||
StartCall = "StartNonSwim",
|
||||
InLiquidAction = "Swim",
|
||||
},
|
||||
Jump = {
|
||||
Prototype = Action,
|
||||
Name = "Jump",
|
||||
Procedure = DFA_FLIGHT,
|
||||
Speed = 100,
|
||||
Accel = 16,
|
||||
Decel = 16,
|
||||
Length = 1,
|
||||
Delay = 0,
|
||||
FacetBase = 1,
|
||||
NextAction = "Jump",
|
||||
StartCall = "StartNonSwim",
|
||||
InLiquidAction = "Swim"
|
||||
},
|
||||
Dead = {
|
||||
Prototype = Action,
|
||||
Name = "Dead",
|
||||
Procedure = DFA_NONE,
|
||||
Speed = 10,
|
||||
Length = 1,
|
||||
Delay = 0,
|
||||
FacetBase=1,
|
||||
Directions = 2,
|
||||
FlipDir = 1,
|
||||
NextAction = "Hold",
|
||||
NoOtherAction = 1,
|
||||
ObjectDisabled = 1
|
||||
}
|
||||
};
|
|
@ -0,0 +1,2 @@
|
|||
Name=Lavakern
|
||||
Description=The lava high life. Has a hard shell on which a clonk may stand, but dangerous due to spitting out lava.
|
|
@ -0,0 +1,2 @@
|
|||
Name=Lavacore
|
||||
Description=The lava high life. Has a hard shell on which a clonk may stand, but dangerous due to spitting out lava.
|
|
@ -19,6 +19,12 @@ protected func Initialize()
|
|||
{
|
||||
score_list = [];
|
||||
|
||||
var relaunch_rule = GetRelaunchRule();
|
||||
relaunch_rule->SetRespawnDelay(0);
|
||||
relaunch_rule->SetDefaultRelaunchCount(nil);
|
||||
relaunch_rule->SetAllowPlayerRestart(true);
|
||||
relaunch_rule.FindRelaunchPos = GetID().FindRelaunchPos;
|
||||
|
||||
// init scoreboard
|
||||
Scoreboard->Init(
|
||||
[
|
||||
|
@ -41,9 +47,9 @@ private func GetScoreGoal()
|
|||
|
||||
public func SetFlagBase(int team, int x, int y)
|
||||
{
|
||||
var base = CreateObject(Goal_FlagBase, x, y, NO_OWNER);
|
||||
var base = CreateObjectAbove(Goal_FlagBase, x, y, NO_OWNER);
|
||||
base->SetTeam(team);
|
||||
var flag = CreateObject(Goal_Flag, x, y, NO_OWNER);
|
||||
var flag = CreateObjectAbove(Goal_Flag, x, y, NO_OWNER);
|
||||
flag->SetAction("AttachBase", base);
|
||||
flag->SetTeam(team);
|
||||
return;
|
||||
|
@ -75,43 +81,24 @@ private func EliminateOthers(int win_team)
|
|||
protected func InitializePlayer(int plr, int x, int y, object base, int team)
|
||||
{
|
||||
// Join new clonk.
|
||||
JoinPlayer(plr);
|
||||
GetRelaunchRule()->DoRelaunch(plr, nil, FindRelaunchPos(plr), true);
|
||||
|
||||
// make scoreboard entry for team
|
||||
Scoreboard->NewEntry(ScoreboardTeamID(team), GetTaggedTeamName(team));
|
||||
|
||||
// Broadcast to scenario.
|
||||
GameCall("OnPlayerRelaunch", plr, false);
|
||||
return _inherited(plr, x, y, base, team, ...);
|
||||
}
|
||||
|
||||
protected func RelaunchPlayer(int plr)
|
||||
public func FindRelaunchPos(int plr)
|
||||
{
|
||||
// New clonk.
|
||||
var clonk = CreateObjectAbove(Clonk, 0, 0, plr);
|
||||
clonk->MakeCrewMember(plr);
|
||||
SetCursor(plr, clonk);
|
||||
// Join new clonk.
|
||||
JoinPlayer(plr);
|
||||
// Broadcast to scenario.
|
||||
GameCall("OnPlayerRelaunch", plr, true);
|
||||
return _inherited(plr, ...);
|
||||
}
|
||||
|
||||
private func JoinPlayer(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
clonk->DoEnergy(100000);
|
||||
var team = GetPlayerTeam(plr);
|
||||
var base = FindObject(Find_ID(Goal_FlagBase), Find_Func("FindTeam", team));
|
||||
if (base)
|
||||
clonk->SetPosition(base->GetX(), base->GetY() - 10);
|
||||
return;
|
||||
return [base->GetX(), base->GetY() - 10];
|
||||
return nil;
|
||||
}
|
||||
|
||||
protected func RemovePlayer(int plr)
|
||||
{
|
||||
|
||||
return _inherited(plr, ...);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,66 +23,19 @@ func Initialize()
|
|||
}
|
||||
maxkills = GameCall("WinKillCount");
|
||||
if(maxkills == nil || maxkills < 1) maxkills = 4;
|
||||
GetRelaunchRule()->SetDefaultRelaunchCount(nil);
|
||||
return _inherited(...);
|
||||
}
|
||||
|
||||
protected func InitializePlayer(int plr)
|
||||
{
|
||||
// Join plr.
|
||||
JoinPlayer(plr);
|
||||
// Scenario script callback.
|
||||
GameCall("OnPlayerRelaunch", plr, false);
|
||||
return _inherited(plr, ...);
|
||||
}
|
||||
|
||||
protected func RelaunchPlayer(int plr, int killer)
|
||||
{
|
||||
_inherited(plr, killer, ...);
|
||||
var clonk = CreateObjectAbove(Clonk, 0, 0, plr);
|
||||
clonk->MakeCrewMember(plr);
|
||||
SetCursor(plr, clonk);
|
||||
JoinPlayer(plr);
|
||||
// Scenario script callback.
|
||||
GameCall("OnPlayerRelaunch", plr, true);
|
||||
// Show scoreboard for a while
|
||||
DoScoreboardShow(1, plr + 1);
|
||||
Schedule(this,Format("DoScoreboardShow(-1, %d)", plr + 1), 35 * ShowBoardTime);
|
||||
NotifyHUD();
|
||||
return;
|
||||
}
|
||||
|
||||
protected func JoinPlayer(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
clonk->DoEnergy(100000);
|
||||
var pos = FindRelaunchPos(plr);
|
||||
clonk->SetPosition(pos[0], pos[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
private func FindRelaunchPos(int plr)
|
||||
{
|
||||
var tx, ty; // Test position.
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
tx = Random(LandscapeWidth());
|
||||
ty = Random(LandscapeHeight());
|
||||
if (GBackSemiSolid(AbsX(tx), AbsY(ty)))
|
||||
continue;
|
||||
if (GBackSemiSolid(AbsX(tx+5), AbsY(ty+10)))
|
||||
continue;
|
||||
if (GBackSemiSolid(AbsX(tx+5), AbsY(ty-10)))
|
||||
continue;
|
||||
if (GBackSemiSolid(AbsX(tx-5), AbsY(ty+10)))
|
||||
continue;
|
||||
if (GBackSemiSolid(AbsX(tx-5), AbsY(ty-10)))
|
||||
continue;
|
||||
// Succes.
|
||||
return [tx, ty];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
public func IsFulfilled()
|
||||
{
|
||||
// Check whether someone has reached the limit.
|
||||
|
@ -94,7 +47,7 @@ public func IsFulfilled()
|
|||
// Otherwise just check if there are no enemies
|
||||
return Goal_Melee->IsFulfilled();
|
||||
// Eliminate all players, that are not in a team with one of the winners
|
||||
for (var i = 0; i < GetPlayerCount(); i++)
|
||||
for (var i = 0; i < GetPlayerCount(); i++)
|
||||
{
|
||||
var plr = GetPlayerByIndex(i);
|
||||
if (winner == plr)
|
||||
|
@ -117,7 +70,7 @@ public func GetDescription(int plr)
|
|||
{
|
||||
var score = GetRelativeScore(plr);
|
||||
if (score.kills > 0)
|
||||
return Format("$MsgAhead$", score.kills, GetPlayerName(score.best));
|
||||
return Format("$MsgAhead$", score.kills, GetPlayerName(score.best));
|
||||
else if (score.kills < 0)
|
||||
return Format("$MsgBehind$", -score.kills, GetPlayerName(score.best));
|
||||
else if (score.best == plr)
|
||||
|
@ -136,7 +89,7 @@ public func Activate(int byplr)
|
|||
else
|
||||
{
|
||||
var score = GetRelativeScore(byplr);
|
||||
if(score.kills > 0) MessageWindow(Format("$MsgAhead$", score.kills, GetPlayerName(score.best)), byplr);
|
||||
if(score.kills > 0) MessageWindow(Format("$MsgAhead$", score.kills, GetPlayerName(score.best)), byplr);
|
||||
else if(score.kills < 0) MessageWindow(Format("$MsgBehind$", -score.kills,GetPlayerName(score.best)), byplr);
|
||||
else if(score.best == byplr) MessageWindow(Format("$MsgYouAreBest$", score.kills), byplr);
|
||||
else MessageWindow(Format("$MsgEqual$", GetPlayerName(score.best)), byplr);
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
Name=Relaunch container
|
||||
MsgRelaunch=You will be relaunched in %d seconds.
|
||||
MsgWeapon=You have %d seconds to choose a weapon.
|
|
@ -1,3 +0,0 @@
|
|||
Name=Relaunch container
|
||||
MsgRelaunch=You will relaunch in %d seconds.
|
||||
MsgWeapon=You have %d seconds to choose a weapon.
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
Premade goal for simple melees with relaunches.
|
||||
Callbacks made to scenario script:
|
||||
* OnPlayerRelaunch(int plr) made when the player is relaunched and at game start plr init.
|
||||
* RelaunchCount() should return the number of relaunches.
|
||||
* KillsToRelaunch() should return how many kills will earn the player an extra relaunch.
|
||||
--*/
|
||||
|
||||
|
@ -19,7 +17,6 @@
|
|||
#include Scoreboard_Relaunch
|
||||
|
||||
// Some rule default values
|
||||
local DefaultRelaunchCount = 5; // Number of relaunches.
|
||||
local DefaultKillsToRelaunch = 4; // Number of kills one needs to make before gaining a relaunch.
|
||||
local ShowBoardTime = 5; // Duration in seconds the scoreboard will be shown to a player on an event.
|
||||
|
||||
|
@ -33,14 +30,6 @@ protected func Initialize()
|
|||
|
||||
/*-- Scenario callbacks --*/
|
||||
|
||||
private func RelaunchCount()
|
||||
{
|
||||
var relaunch_cnt = GameCall("RelaunchCount");
|
||||
if (relaunch_cnt != nil)
|
||||
return relaunch_cnt;
|
||||
return DefaultRelaunchCount;
|
||||
}
|
||||
|
||||
private func KillsToRelaunch()
|
||||
{
|
||||
var kills_to_relaunch = GameCall("KillsToRelaunch");
|
||||
|
@ -53,21 +42,12 @@ private func KillsToRelaunch()
|
|||
|
||||
protected func InitializePlayer(int plr)
|
||||
{
|
||||
// First process relaunches, etc.
|
||||
_inherited(plr, ...);
|
||||
// Join plr.
|
||||
JoinPlayer(plr);
|
||||
// Scenario script callback.
|
||||
GameCall("OnPlayerRelaunch", plr, false);
|
||||
return;
|
||||
}
|
||||
|
||||
protected func RelaunchPlayer(int plr, int killer)
|
||||
{
|
||||
_inherited(plr, killer, ...);
|
||||
if (GetRelaunchCount(plr) < 0)
|
||||
return EliminatePlayer(plr);
|
||||
|
||||
// the kill logs rule cares about logging the respawn
|
||||
// ..
|
||||
|
||||
|
@ -78,54 +58,15 @@ protected func RelaunchPlayer(int plr, int killer)
|
|||
if (!(GetPlayerTeam(killer) && GetPlayerTeam(killer) == GetPlayerTeam(plr)))
|
||||
if (KillsToRelaunch() && !(GetKillCount(killer) % KillsToRelaunch()) && GetKillCount(killer))
|
||||
{
|
||||
DoRelaunchCount(killer, 1);
|
||||
GetRelaunchRule()->DoPlayerRelaunchCount(killer, 1);
|
||||
Log("$MsgRelaunchGained$", GetPlayerName(killer));
|
||||
}
|
||||
|
||||
var clonk = CreateObjectAbove(Clonk, 0, 0, plr);
|
||||
clonk->MakeCrewMember(plr);
|
||||
SetCursor(plr, clonk);
|
||||
JoinPlayer(plr);
|
||||
// Scenario script callback.
|
||||
GameCall("OnPlayerRelaunch", plr, true);
|
||||
// Show scoreboard for a while.
|
||||
DoScoreboardShow(1, plr + 1);
|
||||
Schedule(this,Format("DoScoreboardShow(-1, %d)", plr + 1), 35 * ShowBoardTime);
|
||||
return;
|
||||
}
|
||||
|
||||
protected func JoinPlayer(int plr)
|
||||
{
|
||||
var clonk = GetCrew(plr);
|
||||
clonk->DoEnergy(100000);
|
||||
var pos = FindRelaunchPos(plr);
|
||||
clonk->SetPosition(pos[0], pos[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
private func FindRelaunchPos(int plr)
|
||||
{
|
||||
var tx, ty; // Test position.
|
||||
for (var i = 0; i < 500; i++)
|
||||
{
|
||||
tx = Random(LandscapeWidth());
|
||||
ty = Random(LandscapeHeight());
|
||||
if (GBackSemiSolid(AbsX(tx), AbsY(ty)))
|
||||
continue;
|
||||
if (GBackSemiSolid(AbsX(tx+5), AbsY(ty+10)))
|
||||
continue;
|
||||
if (GBackSemiSolid(AbsX(tx+5), AbsY(ty-10)))
|
||||
continue;
|
||||
if (GBackSemiSolid(AbsX(tx-5), AbsY(ty+10)))
|
||||
continue;
|
||||
if (GBackSemiSolid(AbsX(tx-5), AbsY(ty-10)))
|
||||
continue;
|
||||
// Succes.
|
||||
return [tx, ty];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
protected func RemovePlayer(int plr)
|
||||
{
|
||||
return _inherited(plr, ...);
|
||||
|
|
|
@ -56,8 +56,9 @@ protected func Initialize(...)
|
|||
|
||||
private func EnsureRestartRule()
|
||||
{
|
||||
if (!ObjectCount(Find_ID(Rule_Restart)))
|
||||
CreateObject(Rule_Restart, Min(64, LandscapeWidth()-GetX()-32), 0, NO_OWNER);
|
||||
var relaunch = GetRelaunchRule();
|
||||
relaunch->SetAllowPlayerRestart(true);
|
||||
relaunch->SetPerformRestart(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -440,7 +441,7 @@ protected func OnClonkDeath(object clonk, int killed_by)
|
|||
JoinPlayer(plr);
|
||||
// Transfer contents if active.
|
||||
if (transfer_contents)
|
||||
Rule_BaseRespawn->TransferInventory(clonk, new_clonk);
|
||||
GetRelaunchRule()->TransferInventory(clonk, new_clonk);
|
||||
// Scenario script callback.
|
||||
GameCall("OnPlayerRespawn", plr, FindRespawnCP(plr));
|
||||
// Log message.
|
||||
|
@ -448,7 +449,8 @@ protected func OnClonkDeath(object clonk, int killed_by)
|
|||
// Respawn actions
|
||||
var cp = FindRespawnCP(plr);
|
||||
UserAction->EvaluateAction(on_respawn, this, clonk, plr);
|
||||
if (cp) cp->OnPlayerRespawn(new_clonk, plr);
|
||||
if (cp)
|
||||
cp->OnPlayerRespawn(new_clonk, plr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -472,7 +474,8 @@ protected func JoinPlayer(int plr)
|
|||
private func FindRespawnCP(int plr)
|
||||
{
|
||||
var respawn_cp = respawn_list[plr];
|
||||
if (!respawn_cp) respawn_cp = respawn_list[plr] = cp_list[0];
|
||||
if (!respawn_cp)
|
||||
respawn_cp = respawn_list[plr] = cp_list[0];
|
||||
return respawn_cp;
|
||||
}
|
||||
|
||||
|
@ -498,10 +501,7 @@ public func SaveScenarioObject(props)
|
|||
{
|
||||
if (!inherited(props, ...))
|
||||
return false;
|
||||
// Force dependency on restart rule.
|
||||
var restart_rule = FindObject(Find_ID(Rule_Restart));
|
||||
if (restart_rule)
|
||||
restart_rule->MakeScenarioSaveName();
|
||||
props->AddCall("Goal", this, "EnsureRestartRule");
|
||||
if (no_respawn_handling)
|
||||
props->AddCall("Goal", this, "DisableRespawnHandling");
|
||||
if (transfer_contents)
|
||||
|
@ -551,19 +551,19 @@ private func UpdateScoreboard(int plr)
|
|||
/*-- Direction indication --*/
|
||||
|
||||
// Effect for direction indication for the clonk.
|
||||
protected func FxIntDirNextCPStart(object target, effect)
|
||||
protected func FxIntDirNextCPStart(object target, effect fx)
|
||||
{
|
||||
var arrow = CreateObjectAbove(GUI_GoalArrow, 0, 0, target->GetOwner());
|
||||
arrow->SetAction("Show", target);
|
||||
effect.arrow = arrow;
|
||||
fx.arrow = arrow;
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
protected func FxIntDirNextCPTimer(object target, effect)
|
||||
protected func FxIntDirNextCPTimer(object target, effect fx)
|
||||
{
|
||||
var plr = target->GetOwner();
|
||||
var team = GetPlayerTeam(plr);
|
||||
var arrow = effect.arrow;
|
||||
var arrow = fx.arrow;
|
||||
// Find nearest CP.
|
||||
var nextcp;
|
||||
for (var cp in FindObjects(Find_ID(ParkourCheckpoint), Find_Func("FindCPMode", PARKOUR_CP_Check | PARKOUR_CP_Finish), Sort_Distance(target->GetX() - GetX(), target->GetY() - GetY())))
|
||||
|
@ -608,9 +608,9 @@ protected func FxIntDirNextCPTimer(object target, effect)
|
|||
return FX_OK;
|
||||
}
|
||||
|
||||
protected func FxIntDirNextCPStop(object target, effect)
|
||||
protected func FxIntDirNextCPStop(object target, effect fx)
|
||||
{
|
||||
effect.arrow->RemoveObject();
|
||||
fx.arrow->RemoveObject();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -820,35 +820,41 @@ func OnMenuEntryHover(proplist menu_info, int entry_index, int player)
|
|||
if (!info.menu.callback_target || !info.menu.callback_hover)
|
||||
{
|
||||
var text = Format("%s:|%s", info.entry.symbol->GetName(), info.entry.symbol.Description);
|
||||
var obj = nil;
|
||||
if (info.entry.extra_data && info.entry.extra_data.objects)
|
||||
{
|
||||
for (var possible in info.entry.extra_data.objects)
|
||||
{
|
||||
if (possible == nil) continue;
|
||||
obj = possible;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// For contents menus, we can sometimes present additional information about objects.
|
||||
if (info.menu.flag == InteractionMenu_Contents && obj)
|
||||
if (info.menu.flag == InteractionMenu_Contents)
|
||||
{
|
||||
var additional = nil;
|
||||
if (obj->Contents())
|
||||
// Get the first valid object of the clicked stack.
|
||||
var obj = nil;
|
||||
if (info.entry.extra_data && info.entry.extra_data.objects)
|
||||
{
|
||||
additional = "$Contains$ ";
|
||||
var i = 0, count = obj->ContentsCount();
|
||||
// This currently justs lists contents one after the other.
|
||||
// Items are not stacked, which should be enough for everything we have ingame right now. If this is filed into the bugtracker at some point, fix here.
|
||||
for (;i < count;++i)
|
||||
for (var possible in info.entry.extra_data.objects)
|
||||
{
|
||||
if (i > 0)
|
||||
additional = Format("%s, ", additional);
|
||||
additional = Format("%s%s", additional, obj->Contents(i)->GetName());
|
||||
if (possible == nil) continue;
|
||||
obj = possible;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (additional != nil)
|
||||
text = Format("%s||%s", text, additional);
|
||||
// ..and use that object to fetch some more information.
|
||||
if (obj)
|
||||
{
|
||||
var additional = nil;
|
||||
if (obj->Contents())
|
||||
{
|
||||
additional = "$Contains$ ";
|
||||
var i = 0, count = obj->ContentsCount();
|
||||
// This currently justs lists contents one after the other.
|
||||
// Items are not stacked, which should be enough for everything we have ingame right now. If this is filed into the bugtracker at some point, fix here.
|
||||
for (;i < count;++i)
|
||||
{
|
||||
if (i > 0)
|
||||
additional = Format("%s, ", additional);
|
||||
additional = Format("%s%s", additional, obj->Contents(i)->GetName());
|
||||
}
|
||||
}
|
||||
if (additional != nil)
|
||||
text = Format("%s||%s", text, additional);
|
||||
}
|
||||
}
|
||||
|
||||
GuiUpdateText(text, current_main_menu_id, 1, current_description_box.desc_target);
|
||||
|
|
|
@ -42,18 +42,38 @@ func PlayBarrelHitSound()
|
|||
Sound("Hits::Materials::Wood::DullWoodHit?");
|
||||
}
|
||||
|
||||
func Collection2(object item)
|
||||
public func Collection2(object item)
|
||||
{
|
||||
UpdateLiquidContainer();
|
||||
return _inherited(item, ...);
|
||||
}
|
||||
|
||||
func Ejection(object item)
|
||||
public func Ejection(object item)
|
||||
{
|
||||
UpdateLiquidContainer();
|
||||
return _inherited(item, ...);
|
||||
}
|
||||
|
||||
public func ContentsDestruction(object item)
|
||||
{
|
||||
ScheduleCall(this, "UpdateLiquidContainer", 1);
|
||||
return _inherited(item, ...);
|
||||
}
|
||||
|
||||
public func RemoveLiquid(liquid_name, int amount, object destination)
|
||||
{
|
||||
var res = _inherited(liquid_name, amount, destination, ...);
|
||||
UpdateLiquidContainer();
|
||||
return res;
|
||||
}
|
||||
|
||||
public func PutLiquid(liquid_name, int amount, object source)
|
||||
{
|
||||
var res = _inherited(liquid_name, amount, source, ...);
|
||||
UpdateLiquidContainer();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*-- Callbacks --*/
|
||||
|
||||
public func CollectFromStack(object item)
|
||||
|
|
|
@ -228,6 +228,11 @@ public func GetCarryTransform()
|
|||
return Trans_Rotate(90, 1, 0, 0);
|
||||
}
|
||||
|
||||
public func OnRelaunchCreation()
|
||||
{
|
||||
CreateContents(LeadBullet);
|
||||
}
|
||||
|
||||
public func Definition(def)
|
||||
{
|
||||
SetProperty("PictureTransformation", Trans_Mul(Trans_Translate(1500, 0, -1500), Trans_Rotate(170, 0, 1, 0), Trans_Rotate(30, 0, 0, 1)), def);
|
||||
|
|
|
@ -232,6 +232,12 @@ public func GetCarrySpecial(clonk)
|
|||
if(fAiming) return "pos_hand2";
|
||||
}
|
||||
|
||||
|
||||
public func OnRelaunchCreation()
|
||||
{
|
||||
CreateContents(Arrow);
|
||||
}
|
||||
|
||||
func Definition(def)
|
||||
{
|
||||
def.PictureTransformation = Trans_Mul(Trans_Translate(-4000,-2000,4000),Trans_Rotate(180,0,1,0),Trans_Rotate(-45,0,0,1));
|
||||
|
|
|
@ -247,6 +247,12 @@ public func GetCarryTransform(object clonk, bool idle, bool nohand, bool second_
|
|||
return Trans_Mul(Trans_Rotate(90,1,0,0), Trans_Rotate(-10,0,0,1));
|
||||
}
|
||||
|
||||
|
||||
public func OnRelaunchCreation()
|
||||
{
|
||||
CreateContents(IronBomb);
|
||||
}
|
||||
|
||||
func Definition(def)
|
||||
{
|
||||
def.PictureTransformation = Trans_Mul(Trans_Translate(-3000, 1000, 1500),Trans_Rotate(170,0,1,0),Trans_Rotate(30,0,0,1));
|
||||
|
|
|
@ -27,7 +27,7 @@ private func AddReproductionEffect()
|
|||
|
||||
private func RemoveReproductionEffect()
|
||||
{
|
||||
return RemoveEffect("IntReproduction");
|
||||
return RemoveEffect("IntReproduction", this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -10,24 +10,14 @@
|
|||
* RemovePlayer(int plr);
|
||||
--*/
|
||||
|
||||
|
||||
local score_relaunch_list; // Here the relaunch count of all players is stored, access through plrid.
|
||||
|
||||
// Overload this.
|
||||
public func RelaunchCount()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
/*-- Callbacks --*/
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
// Make sure it is a list.
|
||||
score_relaunch_list = [];
|
||||
// init scoreboard
|
||||
// init scoreboard, uses the condition of Scoreboard_Deaths too
|
||||
Scoreboard->Init(
|
||||
if (GetRelaunchRule()->HasUnlimitedRelaunches()) return;
|
||||
Scoreboard->Init(
|
||||
[{key = "relaunches", title = Scoreboard_Relaunch, sorted = true, desc = true, default = "", priority = 75, conditional = Scoreboard_Death.ScoreboardCondition}]
|
||||
);
|
||||
return _inherited(...);
|
||||
|
@ -35,20 +25,16 @@ protected func Initialize()
|
|||
|
||||
protected func InitializePlayer(int plr)
|
||||
{
|
||||
var plrid = GetPlayerID(plr);
|
||||
// create scoreboard entry
|
||||
score_relaunch_list[plrid] = RelaunchCount();
|
||||
if (GetRelaunchRule()->HasUnlimitedRelaunches()) return;
|
||||
Scoreboard->NewPlayerEntry(plr);
|
||||
Scoreboard->SetPlayerData(plr, "relaunches", score_relaunch_list[plrid]);
|
||||
Scoreboard->SetPlayerData(plr, "relaunches", GetRelaunchRule()->GetPlayerRelaunchCount(plr));
|
||||
return _inherited(plr, ...);
|
||||
}
|
||||
|
||||
protected func RelaunchPlayer(int plr, int killer)
|
||||
{
|
||||
var plrid = GetPlayerID(plr);
|
||||
// Modify scoreboard relaunch count entry for this player.
|
||||
score_relaunch_list[plrid]--;
|
||||
Scoreboard->SetPlayerData(plr, "relaunches", score_relaunch_list[plrid]);
|
||||
if (GetRelaunchRule()->HasUnlimitedRelaunches()) return;
|
||||
Scoreboard->SetPlayerData(plr, "relaunches", GetRelaunchRule()->GetPlayerRelaunchCount(plr));
|
||||
return _inherited(plr, killer, ...);
|
||||
}
|
||||
|
||||
|
@ -59,26 +45,6 @@ protected func RemovePlayer(int plr)
|
|||
|
||||
/*-- Misc --*/
|
||||
|
||||
public func SetRelaunchCount(int plr, int value)
|
||||
{
|
||||
var plrid = GetPlayerID(plr);
|
||||
score_relaunch_list[plrid] = value;
|
||||
Scoreboard->SetPlayerData(plr, "relaunches", score_relaunch_list[plrid]);
|
||||
return;
|
||||
}
|
||||
|
||||
public func GetRelaunchCount(int plr)
|
||||
{
|
||||
var plrid = GetPlayerID(plr);
|
||||
return score_relaunch_list[plrid];
|
||||
}
|
||||
|
||||
public func DoRelaunchCount(int plr, int value)
|
||||
{
|
||||
var plrid = GetPlayerID(plr);
|
||||
score_relaunch_list[plrid] += value;
|
||||
Scoreboard->SetPlayerData(plr, "relaunches", score_relaunch_list[plrid]);
|
||||
return;
|
||||
}
|
||||
|
||||
local Name = "Scoreboard Relaunches";
|
||||
|
|
|
@ -1,185 +1,10 @@
|
|||
/**
|
||||
Base Respawn
|
||||
If neutral flagpoles are available, respawn there (for free). Otherwise, respawn
|
||||
at the nearest base if sufficient clonks and clunkers are available.
|
||||
TODO: make more general for all kinds of available crew members.
|
||||
|
||||
@author Maikel, Sven2
|
||||
*/
|
||||
/* Converts itself to the Rule_Relaunch rule. */
|
||||
|
||||
// Determines whether the inventory of the crew member is transfered upon respawn.
|
||||
local inventory_transfer = false;
|
||||
|
||||
// Determines whether a crew member needs to be bought.
|
||||
local free_crew = false;
|
||||
|
||||
// Delay between clonk death and respawn (in seconds)
|
||||
local respawn_delay = 2;
|
||||
|
||||
protected func Initialize()
|
||||
protected func Construction()
|
||||
{
|
||||
ScheduleCall(this, this.CheckDescription, 1, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
private func CheckDescription()
|
||||
{
|
||||
// If neutral flagpoles exist, update name and description.
|
||||
if (ObjectCount(Find_ID(Flagpole), Find_Func("IsNeutral")))
|
||||
{
|
||||
SetName("$Name2$");
|
||||
this.Description = "$Description2$";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public func SetInventoryTransfer(bool transfer)
|
||||
{
|
||||
inventory_transfer = transfer;
|
||||
return true;
|
||||
}
|
||||
|
||||
public func GetInventoryTransfer()
|
||||
{
|
||||
return inventory_transfer;
|
||||
}
|
||||
|
||||
public func SetFreeCrew(bool free)
|
||||
{
|
||||
free_crew = free;
|
||||
return true;
|
||||
}
|
||||
|
||||
public func GetFreeCrew()
|
||||
{
|
||||
return free_crew;
|
||||
}
|
||||
|
||||
protected func OnClonkDeath(object clonk)
|
||||
{
|
||||
var plr = clonk->GetOwner();
|
||||
// Skip eliminated players, NO_OWNER, etc.
|
||||
if (!GetPlayerName(plr))
|
||||
return true;
|
||||
|
||||
// Only respawn a clonk if it is the last crew member.
|
||||
if (GetCrewCount(plr) >= 1)
|
||||
return true;
|
||||
|
||||
// Get the bases at which the clonk can possibly respawn.
|
||||
var bases = GetBases(clonk), crew;
|
||||
for (var base in bases)
|
||||
{
|
||||
if (!base)
|
||||
continue;
|
||||
|
||||
// If free crew just create a clonk at the base.
|
||||
if (free_crew)
|
||||
{
|
||||
crew = CreateObjectAbove(Clonk, base->GetX() - GetX(), base->GetY() + base->GetDefHeight() / 2 - GetY(), plr);
|
||||
crew->MakeCrewMember(plr);
|
||||
SetCursor(plr, crew);
|
||||
// Transfer inventory if turned on.
|
||||
if (inventory_transfer) TransferInventory(clonk, crew);
|
||||
break;
|
||||
}
|
||||
// Try to buy a crew member at the base.
|
||||
var pay_plr = base->GetOwner();
|
||||
// Payment in neutral bases by clonk owner.
|
||||
if (pay_plr == NO_OWNER)
|
||||
pay_plr = plr;
|
||||
crew = base->~DoBuy(Clonk, plr, pay_plr, clonk);
|
||||
if (crew)
|
||||
{
|
||||
crew->Exit(0, base->GetDefHeight() / 2);
|
||||
SetCursor(plr, crew);
|
||||
// Transfer inventory if turned on.
|
||||
if (inventory_transfer) TransferInventory(clonk, crew);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Respawn delay (+Weapon choice if desired by scenario)
|
||||
if (crew && respawn_delay)
|
||||
{
|
||||
crew->SetCrewEnabled(false); // will be re-set by relauncher
|
||||
var relaunch = CreateObject(RelaunchContainer, crew->GetX() - GetX(), crew->GetY() - GetY(), plr);
|
||||
relaunch->SetRelaunchTime(respawn_delay, false);
|
||||
relaunch->StartRelaunch(crew);
|
||||
// But keep view on old corpse because the death might be exciting!
|
||||
// And sometimes you want to know why you died (just like in real-life!)
|
||||
var light = CreateLight(clonk->GetX() - GetX(), clonk->GetY() - GetY(), 100, Fx_Light.LGT_Temp, plr, 20, respawn_delay*36);
|
||||
SetCursor(plr, nil);
|
||||
SetPlrView(plr, light);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private func TransferInventory(object from, object to)
|
||||
{
|
||||
// Drop some items that cannot be transferred (such as connected pipes and dynamite igniters)
|
||||
var i = from->ContentsCount(), contents;
|
||||
while (i--)
|
||||
if (contents = from->Contents(i))
|
||||
if (contents->~IsDroppedOnDeath(from))
|
||||
{
|
||||
contents->Exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The new clonk doesn't burn. To be consistent, also extinguish contents
|
||||
contents->Extinguish();
|
||||
}
|
||||
return to->GrabContents(from);
|
||||
}
|
||||
|
||||
private func GetBases(object clonk)
|
||||
{
|
||||
var plr = clonk->GetOwner();
|
||||
// Neutral flagpoles are preferred respawn points, because they are used as the only respawn points in missions.
|
||||
var bases = clonk->FindObjects(Find_ID(Flagpole), Find_Func("IsNeutral"), clonk->Sort_Distance());
|
||||
// If there are no neutral flagpoles, find closest base owned by the player (or team) and try to buy a clonk.
|
||||
if (GetLength(bases) <= 0)
|
||||
bases = clonk->FindObjects(Find_Func("IsBaseBuilding"), Find_Allied(plr), clonk->Sort_Distance());
|
||||
return bases;
|
||||
}
|
||||
|
||||
protected func Activate(int byplr)
|
||||
{
|
||||
MessageWindow(this.Description, byplr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*-- Scenario saving --*/
|
||||
|
||||
public func SaveScenarioObject(props, ...)
|
||||
{
|
||||
if (!inherited(props, ...))
|
||||
return false;
|
||||
// Custom properties
|
||||
props->Remove("Name"); // updated by initialization
|
||||
props->Remove("Description"); // updated by initialization
|
||||
if (inventory_transfer)
|
||||
props->AddCall("InvenctoryTransfer", this, "SetInventoryTransfer", inventory_transfer);
|
||||
if (free_crew)
|
||||
props->AddCall("FreeCrew", this, "SetFreeCrew", free_crew);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Editor */
|
||||
|
||||
public func Definition(def)
|
||||
{
|
||||
if (!def.EditorProps) def.EditorProps = {};
|
||||
def.EditorProps.inventory_transfer = { Name="$InventoryTransfer$", EditorHelp="$InventoryTransferHelp$", Type="bool", Set="SetInventoryTransfer" };
|
||||
def.EditorProps.free_crew = { Name="$FreeCrew$", EditorHelp="$FreeCrewHelp$", Type="bool", Set="SetFreeCrew" };
|
||||
}
|
||||
|
||||
|
||||
/*-- Proplist --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Visibility = VIS_Editor;
|
||||
local EditorPlacementLimit = 1; // Rules are to be placed only once
|
||||
var relaunch_rule = GetRelaunchRule();
|
||||
relaunch_rule->SetBaseRespawn(true);
|
||||
relaunch_rule->SetFreeCrew(false);
|
||||
relaunch_rule->SetLastClonkRespawn(true);
|
||||
return RemoveObject();
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
Name=Basis Neustart
|
||||
Name2=Neustart am Flaggenmast
|
||||
Description=Du wirst in der nächstliegenden Basis wiederbelebt, wenn ausreichend Clonks und Clunker vorhanden sind.
|
||||
Description2=Du wirst am nächstliegenden Flaggenmast wiederbelebt.
|
||||
InventoryTransfer=Inventar behalten
|
||||
InventoryTransferHelp=Ob das Inventar sterbender Clonks beim Respawn zum neuen Clonk teleportiert werden soll.
|
||||
FreeCrew=Kostenloser Respawn
|
||||
FreeCrewHelp=Ob man die Clonks umsonst bekommt.
|
|
@ -1,8 +0,0 @@
|
|||
Name=Base Respawn
|
||||
Name2=Respawn at flagpole
|
||||
Description=You respawn at the nearest base if sufficient clonks and clunkers are available.
|
||||
Description2=You respawn at the nearest respawn flagpole.
|
||||
InventoryTransfer=Keep inventory
|
||||
InventoryTransferHelp=Whether the inventory of dying clonks is beamed to the newly respawned clonk.
|
||||
FreeCrew=Free respawn
|
||||
FreeCrewHelp=Whether respawning clonks are free. If not set, respawn happens only if the player has sufficient gold and clonks available for sale.
|
|
@ -42,16 +42,7 @@ func OnClonkDeathEx(object clonk, int plr, int killed_by)
|
|||
log=Format(Translate(Format("Teamkill%d", which_one)), GetTaggedPlayerName(plr), name, GetTaggedPlayerName(killed_by));
|
||||
else log=Format(Translate(Format("KilledByPlayer%d", which_one)), GetTaggedPlayerName(plr), name, GetTaggedPlayerName(killed_by));
|
||||
|
||||
// okay, why is GetRelaunchCount not a global function..?
|
||||
// and why are the relaunches not stored in a static variable or a singleton that can be accessed somehow..
|
||||
var relaunches=nil;
|
||||
for(var goal in FindObjects(Find_Or(Find_Category(C4D_Goal), Find_Category(C4D_Rule))))
|
||||
{
|
||||
relaunches = goal->~GetRelaunchCount(plr);
|
||||
if(relaunches != nil) break;
|
||||
}
|
||||
if(relaunches == nil) relaunches=GameCall("GetRelaunchCount", plr);
|
||||
|
||||
var relaunches = GetRelaunchRule()->GetPlayerRelaunchCount(plr);
|
||||
if(relaunches != nil)
|
||||
{
|
||||
var msg="";
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
[DefCore]
|
||||
id=Rule_Relaunch
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack | C4D_Rule
|
||||
Width=32
|
||||
Height=32
|
||||
Offset=-16,-16
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
@ -3,34 +3,28 @@
|
|||
Author: Maikel
|
||||
|
||||
This container holds the clonk after relaunches.
|
||||
* The time the clonk is held can be specified with SetRelaunchTime(int time);
|
||||
* The time the clonk is held can be specified by calling GetRelaunchRule()->SetRespawnDelay(int time).
|
||||
* After that time the clonk is released and OnClonkLeftRelaunch(object clonk) is called in the scenario script.
|
||||
* Optionally the clonk can choose a weapon if GetRelaunchWeaponList in the scenario script returns a valid id-array.
|
||||
--*/
|
||||
|
||||
local time;
|
||||
local menu;
|
||||
local hold;
|
||||
local has_selected;
|
||||
|
||||
local crew;
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
time = 36 * 10;
|
||||
return;
|
||||
}
|
||||
local hold_crew = false;
|
||||
local relaunch_time = 36 * 10;
|
||||
|
||||
// Sets the time, in seconds, the clonk is held in the container.
|
||||
public func SetRelaunchTime(int to_time, bool to_hold)
|
||||
{
|
||||
time = to_time * 36;
|
||||
hold = to_hold;
|
||||
relaunch_time = to_time * 36;
|
||||
hold_crew = to_hold;
|
||||
return;
|
||||
}
|
||||
|
||||
// Returns the time, in seconds the clonk is held.
|
||||
public func GetRelaunchTime() { return time / 36; }
|
||||
public func GetRelaunchTime() { return relaunch_time / 36; }
|
||||
|
||||
// Retrieve weapon list from scenario.
|
||||
private func WeaponList() { return GameCall("RelaunchWeaponList"); }
|
||||
|
@ -39,15 +33,14 @@ public func StartRelaunch(object clonk)
|
|||
{
|
||||
if (!clonk)
|
||||
return;
|
||||
// only 1 clonk can be inside
|
||||
if(crew)
|
||||
// Only 1 clonk can be inside.
|
||||
if (crew)
|
||||
return;
|
||||
// save clonk for later use
|
||||
// Save clonk for later use.
|
||||
crew = clonk;
|
||||
clonk->Enter(this);
|
||||
ScheduleCall(this, "OpenWeaponMenu", 36, 0, clonk);
|
||||
AddEffect("IntTimeLimit", this, 100, 36, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -62,49 +55,59 @@ private func OpenWeaponMenu(object clonk)
|
|||
{
|
||||
menu = CreateObject(MenuStyle_Default, nil, nil, clonk->GetOwner());
|
||||
menu->SetPermanent();
|
||||
menu->SetTitle(Format("$MsgWeapon$", time / 36));
|
||||
clonk->SetMenu(menu, true);
|
||||
menu->SetTitle(Format("$MsgWeapon$", relaunch_time / 36));
|
||||
clonk->SetMenu(menu, true);
|
||||
|
||||
if (GetType(GetRelaunchRule().last_used_player_weapons) != C4V_Array)
|
||||
GetRelaunchRule().last_used_player_weapons = [];
|
||||
for (var weapon in weapons)
|
||||
menu->AddItem(weapon, weapon->GetName(), nil, this, "OnWeaponSelected", weapon);
|
||||
{
|
||||
if (GetRelaunchRule().last_used_player_weapons[clonk->GetOwner()] != weapon)
|
||||
{
|
||||
menu->AddItem(weapon, weapon->GetName(), nil, this, "OnWeaponSelected", weapon);
|
||||
}
|
||||
}
|
||||
|
||||
menu->Open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func FxIntTimeLimitTimer(object target, effect, int fxtime)
|
||||
public func FxIntTimeLimitTimer(object target, effect fx, int fxtime)
|
||||
{
|
||||
var clonk = crew;
|
||||
if (!clonk)
|
||||
{
|
||||
RemoveObject();
|
||||
return -1;
|
||||
return FX_Execute_Kill;
|
||||
}
|
||||
if (fxtime >= time)
|
||||
if (fxtime >= relaunch_time)
|
||||
{
|
||||
if (!has_selected && WeaponList())
|
||||
GiveWeapon(WeaponList()[Random(GetLength(WeaponList()))]);
|
||||
GiveWeapon(RandomElement(WeaponList()));
|
||||
RelaunchClonk();
|
||||
return -1;
|
||||
return FX_Execute_Kill;
|
||||
}
|
||||
if (menu)
|
||||
menu->SetTitle(Format("$MsgWeapon$", (time - fxtime) / 36));
|
||||
menu->SetTitle(Format("$MsgWeapon$", (relaunch_time - fxtime) / 36));
|
||||
else
|
||||
PlayerMessage(clonk->GetOwner(), Format("$MsgRelaunch$", (time - fxtime) / 36));
|
||||
return 1;
|
||||
PlayerMessage(clonk->GetOwner(), Format("$MsgRelaunch$", (relaunch_time - fxtime) / 36));
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
public func OnWeaponSelected(id weapon)
|
||||
{
|
||||
if (!crew)
|
||||
return;
|
||||
GiveWeapon(weapon);
|
||||
|
||||
if (GetRelaunchRule()->GetLastWeaponUse())
|
||||
GetRelaunchRule().last_used_player_weapons[crew->GetOwner()] = weapon;
|
||||
has_selected = true;
|
||||
// Close menu manually, to prevent selecting more weapons.
|
||||
if (menu)
|
||||
menu->Close();
|
||||
|
||||
if (!hold)
|
||||
if (!hold_crew)
|
||||
RelaunchClonk();
|
||||
return true;
|
||||
}
|
||||
|
@ -112,7 +115,7 @@ public func OnWeaponSelected(id weapon)
|
|||
private func RelaunchClonk()
|
||||
{
|
||||
var clonk = crew;
|
||||
// When relaunching from disabled state (i.e base respawn), reset view to clonk
|
||||
// When relaunching from disabled state (i.e base respawn), reset view to clonk.
|
||||
if (!clonk->GetCrewEnabled())
|
||||
{
|
||||
clonk->SetCrewEnabled(true);
|
||||
|
@ -120,7 +123,7 @@ private func RelaunchClonk()
|
|||
SetPlrView(clonk->GetOwner(), clonk);
|
||||
}
|
||||
clonk->Exit();
|
||||
GameCall("OnClonkLeftRelaunch", clonk);
|
||||
GameCall("OnClonkLeftRelaunch", clonk, clonk->GetOwner());
|
||||
if (menu)
|
||||
menu->Close();
|
||||
PlayerMessage(clonk->GetOwner(), "");
|
||||
|
@ -131,14 +134,12 @@ private func RelaunchClonk()
|
|||
private func GiveWeapon(id weapon_id)
|
||||
{
|
||||
var newobj = CreateObjectAbove(weapon_id);
|
||||
if (weapon_id == Bow)
|
||||
newobj->CreateContents(Arrow);
|
||||
if (weapon_id == Blunderbuss)
|
||||
newobj->CreateContents(LeadBullet);
|
||||
newobj->~OnRelaunchCreation(crew);
|
||||
crew->Collect(newobj);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
public func SaveScenarioObject() { return false; }
|
||||
|
||||
local Name = "$Name$";
|
||||
/*-- Saving --*/
|
||||
|
||||
public func SaveScenarioObject() { return false; }
|
|
@ -0,0 +1,2 @@
|
|||
MsgRelaunch=You will be relaunched in %d seconds.
|
||||
MsgWeapon=You have %d seconds to choose a weapon.
|
|
@ -0,0 +1,2 @@
|
|||
MsgRelaunch=You will relaunch in %d seconds.
|
||||
MsgWeapon=You have %d seconds to choose a weapon.
|
|
@ -0,0 +1,480 @@
|
|||
/**
|
||||
Relaunch Rule
|
||||
This rule enables and handles relaunches with its various aspects. These are:
|
||||
* SetInventoryTransfer(bool transfer): inventory of crew is transferred on respawn [default false].
|
||||
* SetFreeCrew(bool free): whether the crew is free or needs to be bought [default false].
|
||||
* SetBaseRespawn(bool set): whether to respawn at a nearby base [default false].
|
||||
* SetLastClonkRespawn(bool b): whether to respawn the last clonk only [default false].
|
||||
* SetRespawnDelay(int delay): respawn delay in seconds [default 10].
|
||||
* SetAllowPlayerRestart(bool on): whether a player can select restart in the rule menu.
|
||||
* SetPerformRestart(bool on): whether this rule actually handles the respawn [default true].
|
||||
* SetDefaultRelaunchCount(int r): the number of relaunches a player has [default nil == infinte].
|
||||
* SetInitialRelaunch(bool on): whether a relaunch on round start is done [default true].
|
||||
The active relaunch rule can be obtained by the global function GetRelaunchRule(). The rule also
|
||||
keeps track of player's actual number of relaunches which can be modified and accessed by:
|
||||
* SetPlayerRelaunchCount(int plr, int value): set player relaunch count.
|
||||
* GetPlayerRelaunchCount(int plr): get player relaunch count.
|
||||
* DoPlayerRelaunchCount(int plr, int value): add to player relaunch count.
|
||||
* HasUnlimitedRelaunches(): whether the players have infinite relaunches.
|
||||
|
||||
@author Maikel, Sven2, Fulgen
|
||||
*/
|
||||
|
||||
|
||||
/*-- Settings --*/
|
||||
|
||||
// Determines whether the inventory of the crew member is transfered upon respawn.
|
||||
local inventory_transfer = false;
|
||||
|
||||
public func SetInventoryTransfer(bool transfer)
|
||||
{
|
||||
inventory_transfer = transfer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetInventoryTransfer() { return inventory_transfer; }
|
||||
|
||||
|
||||
// Determines whether a crew member needs to be bought.
|
||||
local free_crew = true;
|
||||
|
||||
public func SetFreeCrew(bool free)
|
||||
{
|
||||
free_crew = free;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetFreeCrew() { return free_crew; }
|
||||
|
||||
|
||||
// Determines whether the clonk will be respawned at the base.
|
||||
local respawn_at_base = false;
|
||||
|
||||
public func SetBaseRespawn(bool set)
|
||||
{
|
||||
respawn_at_base = set;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetBaseRespawn() { return respawn_at_base; }
|
||||
|
||||
|
||||
// Determines whether only the last clonk gets respawned.
|
||||
local respawn_last_clonk = false;
|
||||
|
||||
public func SetLastClonkRespawn(bool b)
|
||||
{
|
||||
respawn_last_clonk = b;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetLastClonkRespawn() { return respawn_last_clonk; }
|
||||
|
||||
|
||||
// Determines the amount of time in the relaunch container.
|
||||
local relaunch_time = 10; // seconds
|
||||
|
||||
public func SetRespawnDelay(int delay)
|
||||
{
|
||||
relaunch_time = delay;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetRespawnDelay() { return relaunch_time / 36; }
|
||||
|
||||
|
||||
// Determines whether a player can select to restart in a round via the rule menu.
|
||||
local allow_restart_player = false;
|
||||
public func SetAllowPlayerRestart(bool on)
|
||||
{
|
||||
allow_restart_player = on;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetAllowPlayerRestart() { return allow_restart_player; }
|
||||
|
||||
|
||||
// Determines whether a relaunch is performed by the rule.
|
||||
local perform_restart = true;
|
||||
|
||||
public func SetPerformRestart(bool on)
|
||||
{
|
||||
perform_restart = on;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetPerformRestart() { return perform_restart; }
|
||||
|
||||
|
||||
// Determines the default relaunch count.
|
||||
local default_relaunch_count = nil;
|
||||
local relaunches = [];
|
||||
|
||||
public func SetDefaultRelaunchCount(int r)
|
||||
{
|
||||
default_relaunch_count = r;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetDefaultRelaunchCount() { return default_relaunch_count; }
|
||||
|
||||
// Determines whether a relaunch is needed on round start.
|
||||
local initial_relaunch = true;
|
||||
|
||||
public func SetInitialRelaunch(bool on)
|
||||
{
|
||||
initial_relaunch = on;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetInitialRelaunch() { return initial_relaunch; }
|
||||
|
||||
|
||||
// Determines whether the crew is released after weapon selection.
|
||||
local hold_crew = false;
|
||||
|
||||
public func SetHolding(bool hold)
|
||||
{
|
||||
hold_crew = hold;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetHolding() { return hold_crew; }
|
||||
|
||||
|
||||
// Determines whether the player can select the last weapon again.
|
||||
local disable_last_weapon = false;
|
||||
local last_used_player_weapons = [];
|
||||
|
||||
public func SetLastWeaponUse(bool use)
|
||||
{
|
||||
disable_last_weapon = !use;
|
||||
return this;
|
||||
}
|
||||
|
||||
public func GetLastWeaponUse() { return disable_last_weapon; }
|
||||
|
||||
|
||||
// Not modifiable at the moment.
|
||||
local respawn_script_players = false;
|
||||
local clonk_type = Clonk;
|
||||
|
||||
|
||||
/*-- Rule Code --*/
|
||||
|
||||
public func Activate(int plr)
|
||||
{
|
||||
// Only restart player if enabled unless this is a definition call.
|
||||
if (this != Rule_Relaunch && !allow_restart_player)
|
||||
return MessageWindow(this.Description, plr);
|
||||
// Notify scenario and stop execution if handled by scenario.
|
||||
if (GameCall("OnPlayerActivatedRestart", plr))
|
||||
return;
|
||||
// Remove the player's clonk, including contents.
|
||||
var clonk = GetCrew(plr);
|
||||
if (clonk && clonk->GetCrewEnabled())
|
||||
{
|
||||
clonk->Kill(clonk, true);
|
||||
clonk->RemoveObject();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public func Initialize()
|
||||
{
|
||||
ScheduleCall(this, this.CheckDescription, 1, 1);
|
||||
if (GetScenarioVal("Mode", "Game") == "Melee")
|
||||
default_relaunch_count = 5;
|
||||
return;
|
||||
}
|
||||
|
||||
private func CheckDescription()
|
||||
{
|
||||
// If neutral flagpoles exist, update name and description.
|
||||
if(respawn_at_base)
|
||||
{
|
||||
if(ObjectCount(Find_ID(Flagpole), Find_Func("IsNeutral")))
|
||||
{
|
||||
SetName("$Name2$");
|
||||
this.Description = "$Description2$";
|
||||
}
|
||||
else
|
||||
{
|
||||
SetName("$Name3$");
|
||||
this.Description = "$Description3$";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetName("$Name$");
|
||||
this.Description = "$Description$";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public func InitializePlayer(int plr)
|
||||
{
|
||||
_inherited(plr, ...);
|
||||
relaunches[plr] = default_relaunch_count;
|
||||
// Check if relaunch is needed.
|
||||
if (!initial_relaunch || !perform_restart)
|
||||
return;
|
||||
// Scenario script callback.
|
||||
if (GameCall("OnPlayerRelaunch", plr, false))
|
||||
return;
|
||||
return DoRelaunch(plr, nil, nil, true);
|
||||
}
|
||||
|
||||
public func OnClonkDeath(object clonk, int killer)
|
||||
{
|
||||
if (!clonk || !perform_restart)
|
||||
return;
|
||||
var plr = clonk->GetOwner();
|
||||
if (plr == NO_OWNER || (!respawn_script_players && GetPlayerType(plr) == C4PT_Script)) return;
|
||||
|
||||
if (default_relaunch_count != nil)
|
||||
{
|
||||
relaunches[plr]--;
|
||||
if (relaunches[plr] < 0)
|
||||
{
|
||||
EliminatePlayer(plr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
GameCall("OnPlayerRelaunch", plr, true);
|
||||
return DoRelaunch(plr, clonk, nil);
|
||||
}
|
||||
|
||||
private func RespawnAtBase(int plr, object clonk)
|
||||
{
|
||||
var base = GetRelaunchBase(plr, clonk);
|
||||
if (base)
|
||||
return [base->GetX(), base->GetY() + base->GetBottom()];
|
||||
return;
|
||||
}
|
||||
|
||||
private func TransferInventory(object from, object to)
|
||||
{
|
||||
if (!from || !to) return;
|
||||
// Drop some items that cannot be transferred (such as connected pipes and dynamite igniters)
|
||||
var i = from->ContentsCount(), contents;
|
||||
while (i--)
|
||||
{
|
||||
if (contents = from->Contents(i))
|
||||
{
|
||||
if (contents->~IsDroppedOnDeath(from))
|
||||
{
|
||||
contents->Exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The new clonk doesn't burn. To be consistent, also extinguish contents
|
||||
contents->Extinguish();
|
||||
}
|
||||
}
|
||||
}
|
||||
return to->GrabContents(from);
|
||||
}
|
||||
|
||||
private func GetRelaunchBase(int plr, object clonk)
|
||||
{
|
||||
plr = plr ?? clonk->GetOwner();
|
||||
// Neutral flagpoles are preferred respawn points, because they are used as the only respawn points in missions.
|
||||
var base = FindObject(Find_ID(Flagpole), Find_Func("IsNeutral"), Sort_Random());
|
||||
if (clonk)
|
||||
clonk->FindObject(Find_ID(Flagpole), Find_Func("IsNeutral"), clonk->Sort_Distance());
|
||||
// If there are no neutral flagpoles, find closest base owned by the player (or team) and try to buy a clonk.
|
||||
if (!base)
|
||||
{
|
||||
base = FindObject(Find_Func("IsBaseBuilding"), Find_Allied(plr), Sort_Random());
|
||||
if (clonk)
|
||||
base = clonk->FindObject(Find_Func("IsBaseBuilding"), Find_Allied(plr), clonk->Sort_Distance());
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
public func DoRelaunch(int plr, object clonk, array position, bool no_creation)
|
||||
{
|
||||
if (!GetPlayerName(plr))
|
||||
return;
|
||||
if (respawn_last_clonk && GetCrewCount(plr) >= 1)
|
||||
return;
|
||||
|
||||
if (respawn_at_base)
|
||||
position = RespawnAtBase(plr, clonk);
|
||||
position = position ?? GameCall("RelaunchPosition", plr, GetPlayerTeam(plr));
|
||||
position = position ?? this->FindRelaunchPos(plr);
|
||||
|
||||
var spawn;
|
||||
// Position array either has the form [x, y] or [[x, y], [x, y], ...].
|
||||
if (GetType(position) == C4V_Array)
|
||||
{
|
||||
if (GetType(position[0]) == C4V_Array)
|
||||
spawn = position[Random(GetLength(position))];
|
||||
else
|
||||
spawn = position;
|
||||
}
|
||||
// If no spawn has been found set it to the middle of the landscape, this should not happen.
|
||||
spawn = spawn ?? [LandscapeWidth() / 2, LandscapeHeight() / 2];
|
||||
|
||||
var new_clonk;
|
||||
if (!no_creation)
|
||||
{
|
||||
if (free_crew)
|
||||
{
|
||||
new_clonk = CreateObjectAbove(clonk_type, spawn[0], spawn[1], plr);
|
||||
if (!new_clonk)
|
||||
return;
|
||||
new_clonk->MakeCrewMember(plr);
|
||||
}
|
||||
else
|
||||
{
|
||||
var base = GetRelaunchBase(plr, clonk);
|
||||
if (!base)
|
||||
return;
|
||||
// Try to buy a crew member at the base.
|
||||
var pay_plr = base->GetOwner();
|
||||
// Payment in neutral bases by clonk owner.
|
||||
if (pay_plr == NO_OWNER)
|
||||
pay_plr = plr;
|
||||
new_clonk = base->~DoBuy(clonk_type, plr, pay_plr, clonk);
|
||||
if (new_clonk)
|
||||
new_clonk->Exit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_clonk = GetCrew(plr);
|
||||
if (!new_clonk)
|
||||
return;
|
||||
}
|
||||
|
||||
if (inventory_transfer)
|
||||
TransferInventory(clonk, new_clonk);
|
||||
|
||||
new_clonk->SetPosition(spawn[0], spawn[1] - new_clonk->GetBottom(), plr);
|
||||
|
||||
if (!GetCursor(plr) || GetCursor(plr) == clonk)
|
||||
SetCursor(plr, new_clonk);
|
||||
new_clonk->DoEnergy(new_clonk.Energy ?? 100000);
|
||||
|
||||
if (relaunch_time)
|
||||
{
|
||||
var container = new_clonk->CreateObject(RelaunchContainer, 0, new_clonk->GetBottom(), plr);
|
||||
container->SetRelaunchTime(relaunch_time, hold_crew);
|
||||
container->StartRelaunch(new_clonk);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected func FindRelaunchPos(int plr)
|
||||
{
|
||||
var loc = FindLocation(Loc_Or(Loc_Sky(), Loc_Tunnel()), Loc_Space(20, CNAT_Top), Loc_Wall(CNAT_Bottom));
|
||||
if (loc == nil)
|
||||
return nil;
|
||||
return [loc.x, loc.y];
|
||||
}
|
||||
|
||||
|
||||
/*-- Scenario Saving --*/
|
||||
|
||||
public func SaveScenarioObject(props, ...)
|
||||
{
|
||||
if (!inherited(props, ...))
|
||||
return false;
|
||||
// Custom properties
|
||||
props->Remove("Name"); // updated by initialization
|
||||
props->Remove("Description"); // updated by initialization
|
||||
if (inventory_transfer)
|
||||
props->AddCall("InventoryTransfer", this, "SetInventoryTransfer", inventory_transfer);
|
||||
if (free_crew)
|
||||
props->AddCall("FreeCrew", this, "SetFreeCrew", free_crew);
|
||||
if (respawn_at_base)
|
||||
props->AddCall("BaseRespawn", this, "SetBaseRespawn", respawn_at_base);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*-- Globals --*/
|
||||
|
||||
// Returns the active relaunch rule, creates one if no exists.
|
||||
global func GetRelaunchRule()
|
||||
{
|
||||
return FindObject(Find_ID(Rule_Relaunch)) || CreateObject(Rule_Relaunch);
|
||||
}
|
||||
|
||||
|
||||
/*-- Player Relaunches --*/
|
||||
|
||||
public func SetPlayerRelaunchCount(int plr, int value)
|
||||
{
|
||||
if (HasUnlimitedRelaunches())
|
||||
return;
|
||||
relaunches[plr] = value;
|
||||
Scoreboard->SetPlayerData(plr, "relaunches", relaunches[plr]);
|
||||
return;
|
||||
}
|
||||
|
||||
public func GetPlayerRelaunchCount(int plr)
|
||||
{
|
||||
return relaunches[plr];
|
||||
}
|
||||
|
||||
public func DoPlayerRelaunchCount(int plr, int value)
|
||||
{
|
||||
if(HasUnlimitedRelaunches())
|
||||
return;
|
||||
relaunches[plr] += value;
|
||||
Scoreboard->SetPlayerData(plr, "relaunches", relaunches[plr]);
|
||||
return;
|
||||
}
|
||||
|
||||
public func HasUnlimitedRelaunches()
|
||||
{
|
||||
return default_relaunch_count == nil;
|
||||
}
|
||||
|
||||
|
||||
/*-- Editor --*/
|
||||
|
||||
public func Definition(proplist def)
|
||||
{
|
||||
if (!def.EditorProps) def.EditorProps = {};
|
||||
def.EditorProps.inventory_transfer = { Name="$InventoryTransfer$", EditorHelp="$InventoryTransferHelp$", Type="bool", Set="SetInventoryTransfer" };
|
||||
def.EditorProps.free_crew = { Name="$FreeCrew$", EditorHelp="$FreeCrewHelp$", Type="bool", Set="SetFreeCrew" };
|
||||
def.EditorProps.respawn_at_base = {
|
||||
Name = "$RespawnAtBase$",
|
||||
EditorHelp = "$RespawnAtBaseHelp$",
|
||||
Type = "bool",
|
||||
Set = "SetBaseRespawn"
|
||||
};
|
||||
|
||||
def.EditorProps.hold = {
|
||||
Name = "$Holding$",
|
||||
EditorHelp = "$HoldingHelp$",
|
||||
Type = "bool",
|
||||
Set = "Setholding"
|
||||
};
|
||||
|
||||
def.EditorProps.respawn_delay = {
|
||||
Name = "$RespawnDelay$",
|
||||
EditorHelp = "$RespawnDelayHelp$",
|
||||
Type = "int",
|
||||
Set = "SetRespawnDelay"
|
||||
};
|
||||
|
||||
def.EditorProps.relaunch_count = {
|
||||
Name = "$RelaunchCount$",
|
||||
EditorHelp = "$RelaunchCountHelp$",
|
||||
Type = "int",
|
||||
Set = "SetDefaultRelaunchCount"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/*-- Proplist --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Visibility = VIS_Editor;
|
||||
local EditorPlacementLimit = 1; // Rules are to be placed only once
|
|
@ -0,0 +1,18 @@
|
|||
Name=Relaunches
|
||||
Name2=Neustart am Flaggenmast
|
||||
Name3=Neustart in der Basis
|
||||
Description=Du wirst an einem vorgegebenen Ort in der Landschaft wiederbelebt.
|
||||
Description2=Du wirst am nächstliegenden Flaggenmast wiederbelebt.
|
||||
Description3=Du wirst in der nächstliegenden Basis wiederbelebt, wenn ausreichend Clonks und Clunker vorhanden sind.
|
||||
InventoryTransfer=Inventar behalten
|
||||
InventoryTransferHelp=Ob das Inventar sterbender Clonks beim Respawn zum neuen Clonk teleportiert werden soll.
|
||||
FreeCrew=Kostenloser Respawn
|
||||
FreeCrewHelp=Ob man die Clonks umsonst bekommt.
|
||||
RespawnAtBase=Respawn bei der Basis
|
||||
RespawnAtBaseHelp=Ob man bei der Basis spawnt.
|
||||
Holding=Clonk bleibt im Container
|
||||
HoldingHelp=Ob der Clonk nach Auswahl einer Waffe im Container bleibt.
|
||||
RespawnDelay=Respawnzeit
|
||||
RespawnDelayHelp=Zeit, die vom Tod bis zum Respawn vergeht.
|
||||
RelaunchCount=Anzahl der Relaunches
|
||||
RelaunchCountHelp=Anzahl der Relaunches, die man erhält. Auf -1 setzen, um unbegrenzte Relaunches zu ermöglichen.
|
|
@ -0,0 +1,18 @@
|
|||
Name=Relaunches
|
||||
Name2=Respawn at flagpole
|
||||
Name3=Base respawn
|
||||
Description=You respawn at a fixed point in the map.
|
||||
Description2=You respawn at the nearest respawn flagpole.
|
||||
Description3=You respawn at the nearest base if sufficient clonks and clunkers are available.
|
||||
InventoryTransfer=Keep inventory
|
||||
InventoryTransferHelp=Whether the inventory of dying clonks is beamed to the newly respawned clonk.
|
||||
FreeCrew=Free respawn
|
||||
FreeCrewHelp=Whether respawning clonks are free. If not set, respawn happens only if the player has sufficient gold and clonks available for sale.
|
||||
RespawnAtBase=Respawn bei der Basis
|
||||
RespawnAtBaseHelp=Ob man bei der Basis spawnt.
|
||||
Holding=Clonks stay in the container
|
||||
HoldingHelp=Whether respawning clonks stay in the container until the respawn time ends.
|
||||
RespawnDelay=Respawn delay
|
||||
RespawnDelayHelp=Time from death to respawning.
|
||||
RelaunchCount=Relaunch count
|
||||
RelaunchCountHelp=Amount of relaunches. Set it to -1 to enable infinite relaunches.
|
|
@ -1,7 +0,0 @@
|
|||
[DefCore]
|
||||
id=Rule_Restart
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack|C4D_Rule
|
||||
Width=32
|
||||
Height=32
|
||||
Offset=-16,-16
|
Before Width: | Height: | Size: 5.2 KiB |
|
@ -1,39 +0,0 @@
|
|||
/*-- Restart --*/
|
||||
|
||||
local remove_contents;
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
// Contents are removed
|
||||
remove_contents = true;
|
||||
return;
|
||||
}
|
||||
|
||||
public func Activate(int plr)
|
||||
{
|
||||
// Notify scenario.
|
||||
if (GameCall("OnPlayerRestart", plr))
|
||||
return;
|
||||
// Remove the player's clonk, including contents.
|
||||
var clonk = GetCrew(plr);
|
||||
if (clonk && clonk->GetCrewEnabled())
|
||||
{
|
||||
// Remove contents only if the Base Respawn Rule isn't there otherwise it will handle inventory
|
||||
if (!ObjectCount(Find_ID(Rule_BaseRespawn)) && remove_contents)
|
||||
while (clonk->Contents())
|
||||
clonk->Contents()->RemoveObject();
|
||||
clonk->Kill(clonk, true);
|
||||
clonk->RemoveObject();
|
||||
}
|
||||
}
|
||||
|
||||
public func SetRemoveContents(bool do_removal)
|
||||
{
|
||||
remove_contents = do_removal;
|
||||
return;
|
||||
}
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Visibility = VIS_Editor;
|
||||
local EditorPlacementLimit = 1; // Rules are to be placed only once
|
|
@ -1,2 +0,0 @@
|
|||
Name=Neu starten
|
||||
Description=Diese Spielregel erlaubt dem Spieler nochmal von vorne zu beginnen.
|