diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/DefCore.txt b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/DefCore.txt new file mode 100644 index 000000000..2a342c704 --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/DefCore.txt @@ -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 \ No newline at end of file diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/Graphics.mesh b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/Graphics.mesh new file mode 100644 index 000000000..513f4d7cf Binary files /dev/null and b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/Graphics.mesh differ diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCore.png b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCore.png new file mode 100644 index 000000000..c960ac7ee Binary files /dev/null and b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCore.png differ diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreNormals.png b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreNormals.png new file mode 100644 index 000000000..b4ee69b61 Binary files /dev/null and b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreNormals.png differ diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/DefCore.txt b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/DefCore.txt new file mode 100644 index 000000000..50a5c2b70 --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/DefCore.txt @@ -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 \ No newline at end of file diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/Graphics.mesh b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/Graphics.mesh new file mode 100644 index 000000000..6ef18f6bd Binary files /dev/null and b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/Graphics.mesh differ diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/LavaCoreShell.png b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/LavaCoreShell.png new file mode 100644 index 000000000..366865802 Binary files /dev/null and b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/LavaCoreShell.png differ diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/LavaCoreShellStone.png b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/LavaCoreShellStone.png new file mode 100644 index 000000000..8c2fa7a22 Binary files /dev/null and b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/LavaCoreShellStone.png differ diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/Scene.material b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/Scene.material new file mode 100644 index 000000000..6a2dfbc44 --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/Scene.material @@ -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 + } + } + } +} diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/Script.c b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/Script.c new file mode 100644 index 000000000..e0351241f --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/Script.c @@ -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(Max(parent->GetCon(), parent.MinSize)); + 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 = 4 * ((size * 20 / 100 + 2) / 4) + 4; + solid_size = BoundBy(solid_size, 4, 28); + var solid_x = (1 + (solid_size - 4) / 4) * (solid_size - 4) / 2; + SetSolidMask(solid_x, 0, solid_size, 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", + } +}; \ No newline at end of file diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/SolidMask.png b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/SolidMask.png new file mode 100644 index 000000000..edd3d85c0 Binary files /dev/null and b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/SolidMask.png differ diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/StringTblDE.txt b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/StringTblDE.txt new file mode 100644 index 000000000..e19b4c5a0 --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/StringTblDE.txt @@ -0,0 +1,2 @@ +Name=Lavacore Shell +Description=Protects the lava core. \ No newline at end of file diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/StringTblUS.txt b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/StringTblUS.txt new file mode 100644 index 000000000..e19b4c5a0 --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreShell.ocd/StringTblUS.txt @@ -0,0 +1,2 @@ +Name=Lavacore Shell +Description=Protects the lava core. \ No newline at end of file diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreStone.png b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreStone.png new file mode 100644 index 000000000..733c6daf1 Binary files /dev/null and b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/LavaCoreStone.png differ diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/Scene.material b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/Scene.material new file mode 100644 index 000000000..73f4cd8d1 --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/Scene.material @@ -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 + } + } + } +} + diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/Script.c b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/Script.c new file mode 100644 index 000000000..745e6e3a9 --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/Script.c @@ -0,0 +1,416 @@ +/** + 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 = 2 * 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) + { + core.MaxSize = Max(core.MinSize, RandomX(settings.size_range[0], settings.size_range[1])); + 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; + // 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(Max(GetCon(), this.MinSize)); + 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 MinSize = 15; +local MaxSize = 50; +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 + } +}; \ No newline at end of file diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/StringTblDE.txt b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/StringTblDE.txt new file mode 100644 index 000000000..6ec5ef623 --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/StringTblDE.txt @@ -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. \ No newline at end of file diff --git a/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/StringTblUS.txt b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/StringTblUS.txt new file mode 100644 index 000000000..1ffca2124 --- /dev/null +++ b/planet/Objects.ocd/Animals.ocd/LavaCore.ocd/StringTblUS.txt @@ -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. \ No newline at end of file diff --git a/planet/Sound.ocg/Animals.ocg/LavaCore.ocg/Fossilize.ogg b/planet/Sound.ocg/Animals.ocg/LavaCore.ocg/Fossilize.ogg new file mode 100644 index 000000000..35ebffb2f Binary files /dev/null and b/planet/Sound.ocg/Animals.ocg/LavaCore.ocg/Fossilize.ogg differ diff --git a/planet/Sound.ocg/authors.txt b/planet/Sound.ocg/authors.txt index 7a927e0b5..62ffcde7e 100644 --- a/planet/Sound.ocg/authors.txt +++ b/planet/Sound.ocg/authors.txt @@ -125,3 +125,4 @@ Kane53126 - Click2 (http://www.freesound.org/people/Kane53126/sounds/257944/) Zywx - MosquitoBuzz (http://www.freesound.org/people/Zywx/sounds/188708/) tc630 - Furnace/Start, Furnace/Stop, Furnace/Loop(http://www.freesound.org/people/tc630/sounds/47835/) kolczok - SawmillRipcut (http://freesound.org/people/kolczok/sounds/198988/) +Maikel - Fossilize (no external source)