HotIce: Add Eci Toh and Miami Ice themes

Thanks to K-Pone and KKenny!
install-platforms
Lukas Werling 2018-01-07 20:59:05 +01:00 committed by Nicolas Hake
parent 5e69a753ad
commit c01cae990e
16 changed files with 436 additions and 10 deletions

View File

@ -5,15 +5,21 @@
@authors Sven2
*/
static g_theme;
// Called be the engine: draw the complete map here.
public func InitializeMap(proplist map)
{
InitTheme();
// Map type 0: One big island; more small islands above
// Map type 1: Only many small islands
var t = SCENPAR_MapType;
var w = map.Wdt, h=map.Hgt;
g_map_width = w;
if (g_theme.BackgroundMat)
map->Draw(g_theme.BackgroundMat, nil, [0,0,w,h]);
// Bottom lava lake
map->Draw("^DuroLava", nil, [0,h*4/5,w,h/5]);
@ -21,15 +27,28 @@ public func InitializeMap(proplist map)
if (t == 1) DrawSmallIslandsMap(map);
// Alternate texctures
var icealt_tex = { Algo=MAPALGO_RndChecker, Wdt=2, Hgt=3 };
var icealt_tex = { Algo=MAPALGO_RndChecker, Wdt=2, Hgt=3, Ratio=g_theme.AltMatRatio };
icealt_tex = { Algo=MAPALGO_Turbulence, Op=icealt_tex };
icealt_tex = { Algo=MAPALGO_And, Op=[Duplicate("Ice"), icealt_tex]};
map->Draw("^Ice-ice", icealt_tex);
icealt_tex = { Algo=MAPALGO_And, Op=[Duplicate(RegexMatch(g_theme.MatNames[1], "\\w+", Regex_FirstOnly)[0][0]), icealt_tex]};
map->Draw(g_theme.MatNames[0], icealt_tex);
// Return true to tell the engine a map has been successfully created.
return true;
}
func InitTheme()
{
var theme = SCENPAR_Theme;
if (theme == 0) // Random Ice
theme = 1 + Random(3);
if (theme == 1) // Hot Ice
return g_theme = HotIce;
if (theme == 2) // Miami Ice
return g_theme = MiamiIce;
if (theme == 3) // Eci Toh
return g_theme = EciToh;
}
func SpawnPositionCount()
{
return Max(Max(GetStartupPlayerCount(), GetPlayerCount()), 2);
@ -42,16 +61,16 @@ func DrawBigIslandMap(proplist map)
// Big
var island = { Algo=MAPALGO_Polygon, X=[0,w,w*6/8,w*2/8], Y=[h*4/10,h*4/10,h*7/10,h*7/10] };
island = { Algo=MAPALGO_Turbulence, Op=island, Amplitude=[0, 8] };
map->Draw("^Ice-ice2", island, [w/10,h*13/20,w*8/10,h*3/20]);
map->Draw(g_theme.MatNames[1], island, [w/10,h*13/20,w*8/10,h*3/20]);
// Make sure one row of inner island is drawn because it's used for player spawns
map->Draw("^Ice-ice2", nil, [w*3/10,h*13/20,w*4/10+1,1]);
map->Draw(g_theme.MatNames[1], nil, [w*3/10,h*13/20,w*4/10+1,1]);
// Smaller floating
var n_islands = 12;
while(n_islands--)
{
var x = w*1/10 + Random(w*8/10);
var y = h*2/10 + Random(h*3/10);
map->Draw("^Ice-ice2", nil, [x,y,1,1]);
map->Draw(g_theme.MatNames[1], nil, [x,y,1,1]);
}
// Player spawns simply in middle of big island
var plrcnt = SpawnPositionCount();
@ -77,7 +96,7 @@ func DrawSmallIslandsMap(proplist map)
szy = 1;
if (y > h/2) szy += Random(2); // lower islands sometimes taller
if (Abs(x-w/2) < w/10) szx += Random(3); // central islands sometimes wider
map->Draw("^Ice-ice2", nil, [x-szx,y,1+2*szx,szy]);
map->Draw(g_theme.MatNames[1], nil, [x-szx,y,1+2*szx,szy]);
}
// Balloon spawn: do nothing further
if (SCENPAR_SpawnType == 1)
@ -90,7 +109,7 @@ func DrawSmallIslandsMap(proplist map)
var x = w*2/10 + i * (w*6/10) / (spawn_island_count - 1);
var y = Max(1, h/10) + Abs(x-w/2) * 3*h/10/w;
if (SCENPAR_Weapons) y += 4; // Grenade launcher mode needs lower starting islands to prevent camping
map->Draw("^Ice-ice2", nil, [x,y,1,1]);
map->Draw(g_theme.MatNames[1], nil, [x,y,1,1]);
g_player_spawn_positions[i] = [x, y-1];
}
return true;

View File

@ -0,0 +1,21 @@
[Material]
Name=BlackIce
Shape=TopFlat
Density=60
Friction=15
DigFree=1
BlastFree=1
Blast2Object=BlackIce
Dig2Object=BlackIce
Dig2ObjectRatio=200
Blast2ObjectRatio=220
MaxAirSpeed=100
MaxSlide=1
Corrode=60
TempConvStrength=3
AboveTempConvert=10
AboveTempConvertDir=1
AboveTempConvertTo=BlackWater
Placement=21
TextureOverlay=black
Soil=1

View File

@ -0,0 +1,14 @@
[Material]
Name=BlackWater
Density=25
Instable=1
MaxAirSpeed=25
MaxSlide=10000
WindDrift=30
Corrode=100
Extinguisher=1
TempConvStrength=3
BelowTempConvert=-10
BelowTempConvertTo=BlackIce
Placement=10
TextureOverlay=black

View File

@ -0,0 +1,20 @@
[Material]
Name=Rock
Shape=TopFlat
Density=60
Friction=15
DigFree=0
BlastFree=1
Blast2Object=Rock
Dig2Object=Rock
Dig2ObjectRatio=200
Blast2ObjectRatio=220
MaxAirSpeed=100
MaxSlide=1
Corrode=60
TempConvStrength=4
AboveTempConvert=10
AboveTempConvertDir=1
AboveTempConvertTo=DuroLava
Placement=21
TextureOverlay=rock

View File

@ -13,7 +13,7 @@ OverloadTextures
22=Acid-acid
23=Lava-lava_red
24=DuroLava-lava_red
25=Water-water
25=BlackWater-black
#26=Oil-Smooth
27=Acid-acid
28=Lava-lava_red
@ -59,7 +59,7 @@ OverloadTextures
66=Ice-ice
67=Ice-ice2
68=Ice-ice2
69=BlackIce-black
70=Snow-snow1
71=Snow-snow1
72=Snow-snow1

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

View File

@ -1,3 +1,31 @@
[ParameterDef]
Name=$Theme$
Description=$DescTheme$
ID=Theme
Default=1
[Options]
[Option]
Name=$HotIce$
Description=$DescHotIce$
Value=1
[Option]
Name=$RandomIce$
Description=$DescRandomIce$
Value=0
[Option]
Name=$MiamiIce$
Description=$DescMiamiIce$
Value=2
[Option]
Name=$EciToh$
Description=$DescEciToh$
Value=3
[ParameterDef]
Name=$MapType$
Description=$DescMapType$

View File

@ -15,6 +15,7 @@ func Initialize()
{key = "wins", title = "Wins", sorted = true, desc = true, default = 0, priority = 100},
{key = "death", title = "", sorted = false, default = "", priority = 0},
]);
}
// Resets the scenario, redrawing the map.
@ -107,6 +108,9 @@ func InitializeRound()
// The game starts after a delay to ensure that everyone is ready.
GUI_Clock->CreateCountdown(3);
SetSky(g_theme.Sky);
g_theme->InitializeRound();
return true;
}
@ -461,3 +465,44 @@ func IsFirestoneSpot(int x, int y)
// Very thorough ice surrounding check so they don't explode right away or when the first layer of ice melts
return GBackSolid(x,y-1) && GBackSolid(x,y+4) && GBackSolid(x-2,y) && GBackSolid(x+2,y);
}
// ============= Themes =============
static const HotIce = new Global {
InitializeRound = func() { },
MatNames = ["^Ice-ice", "^Ice-ice2"],
AltMatRatio = 50,
BackgroundMat = nil,
Sky = "Default",
};
static const EciToh = new HotIce {
MatNames = ["Coal", "Rock-rock"],
AltMatRatio = 8,
BackgroundMat = "Tunnel",
};
static const MiamiIce = new HotIce {
MatNames = ["^BlackIce-black", "^BlackIce-black"],
Sky = "SkyMiami",
InitializeRound = func()
{
// Colors
Scenario->CreateEffect(MiamiObjects, 1, 1);
Tree_Coconut->Place(RandomX(7, 13));
},
MiamiObjects = new Effect {
Timer = func(int time)
{
for (var o in FindObjects(Find_NoContainer()))
{
if (o->GetID() == Tree_Coconut)
continue;
o->SetClrModulation(HSL(time, 255, 100));
}
},
},
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

View File

@ -1,21 +1,35 @@
Theme=Thema
DescTheme=Genug Eis gesehen?
HotIce=Heißes Eis
DescHotIce=Das Übliche: Eis und Lava
RandomIce=Random Eis
DescRandomIce=Zufälliges Thema jede Runde
MiamiIce=Miami Eis
DescMiamiIce=Augenkrebs
EciToh=Eci Toh
DescEciToh=Was mag der Name nur bedeuten?!
MapType=Karte
DescMapType=Definiert die Landschaftsform.
MapTypeBigIsland=Große Insel
DescMapTypeBigIsland=Eine zentrale Hauptinsel mit einigen Eisflecken in der Luft.
MapTypeSpots=Kleine inseln
DescMapTypeSpots=Viele kleine Eisflecken in der Luft.
Weapons=Waffen
DescWeapons=Setzt fest welche Angriffsmittel den Spielern zur Verfügung stehen.
WeaponsClassic=Klassisch
DescWeaponsClassic=Bögen, Speere, Keulen und einige Feuersteine
WeaponsExplosive=Explosiv
DescWeaponsExplosive=Nur Granatwerfer mit Endlosmunition
SpawnType=Startpunkte
DescSpawn=Legt fest, wo die Clonks der Spieler starten.
ClassicSpawn=Klassisch
DescClassicSpawn=Die Clonks starten auf den Eisinseln.
BalloonSpawn=Ballons
DescBalloonSpawn=Die Clonks fallen mit Ballons vom Himmel.
Rounds=Rundenzahl
DescRounds=Mehrere Runden spielen
Stalemate=Unentschieden!

View File

@ -1,21 +1,35 @@
Theme=Theme
DescTheme=In case you don't like ice.
HotIce=Hot Ice
DescHotIce=The standard setup: ice and lava
RandomIce=Random Ice
DescRandomIce=Random theme every round
MiamiIce=Miami Ice
DescMiamiIce=Cool Ice
EciToh=Eci Toh
DescEciToh=Battle on rocky islands!
MapType=Map
DescMapType=Defines the shape of the landscape.
MapTypeBigIsland=Big island
DescMapTypeBigIsland=One central main island with small spots of ice in the air above.
MapTypeSpots=Small islands
DescMapTypeSpots=Many small spots of ice in the air.
Weapons=Weapons
DescWeapons=Defines which weapons are available for players.
WeaponsClassic=Classic
DescWeaponsClassic=Bows, spears and clubs available in chests.
WeaponsExplosive=Explosive
DescWeaponsExplosive=Only grenade lauchers and wind bags available.
SpawnType=Spawn points
DescSpawn=Defines where the starting positions will be.
ClassicSpawn=Classic
DescClassicSpawn=All clonks start on the ice islands.
BalloonSpawn=Balloons
DescBalloonSpawn=The clonks will drop with balloons from the sky.
Rounds=Number of rounds
DescRounds=Play for multiple rounds.
Stalemate=Stalemate!

View File

@ -0,0 +1,43 @@
#appendto Boompack
protected func FxFlightTimer(object pTarget, effect, int iEffectTime)
{
if (g_theme != MiamiIce) return inherited(pTarget, effect, iEffectTime, ...);
// clonk does sense the danger and with great presence of mind jumps of the rocket
if(fuel<20 && rider)
{
JumpOff(rider,30);
}
if(!Random(105)) Sound("Fire::Cracker");
if(fuel<=0)
{
DoFireworks();
return;
}
var ignition = iEffectTime % 9;
if(!ignition)
{
var angle = GetR()+RandomX(-dirdev,dirdev);
SetXDir(3*GetXDir()/4+Sin(angle,24));
SetYDir(3*GetYDir()/4-Cos(angle,24));
SetR(angle);
}
var x = -Sin(GetR(), 10);
var y = +Cos(GetR(), 10);
var xdir = GetXDir() / 2;
var ydir = GetYDir() / 2;
if(!effect.clr)
effect.clr = HSL(Random(255), 255, 100);
CreateParticle("FireDense", x, y, PV_Random(xdir - 4, xdir + 4), PV_Random(ydir - 4, ydir + 4), PV_Random(16, 38), Particles_Colored(Particles_Thrust(), effect.clr), 5);
fuel--;
}

View File

@ -0,0 +1,37 @@
#appendto Tree_Coconut
public func Construction()
{
if (g_theme == MiamiIce)
SetClrModulation(RGB());
return _inherited();
}
public func BurstIntoAshes()
{
if (g_theme != MiamiIce) return inherited(...);
var particles =
{
Prototype = Particles_Dust(),
R = 50, G = 50, B = 50,
Size = PV_KeyFrames(0, 0, 0, 200, PV_Random(2, 10), 1000, 0),
};
var r = GetR();
var size = GetCon() * 110 / 100;
for(var cnt = 0; cnt < 10; ++cnt)
{
var distance = Random(size/2);
var x = Sin(r, distance);
var y = -Cos(r, distance);
for(var mirror = -1; mirror <= 1; mirror += 2)
{
CreateParticle("Dust", x * mirror, y * mirror, PV_Random(-3, 3), PV_Random(-3, -3), PV_Random(18, 1 * 36), particles, 2);
CastPXS("BlackIce", 5, 30, x * mirror, y * mirror);
}
}
RemoveObject();
}

View File

@ -0,0 +1,116 @@
/*
Contains functions for (visual) effects that require particles or definitions from Objects.ocd to be loaded.
*/
/*
Creates a visual explosion effect at a position.
smoothness (in percent) determines how round the effect will look like
*/
global func ExplosionEffect(int level, int x, int y, int smoothness, bool silent, int damage_level)
{
if (g_theme != MiamiIce) return inherited(level, x, y, smoothness, silent, damage_level, ...);
// Zero-size explosion doesn't affect anything
if (level <= 0) return;
if(!silent) //Does object use it's own explosion sound effect?
{
// Select sound according to level: from 1 to 3, add the * to allow alternatives.
var grade = BoundBy(level / 10 - 1, 1, 3);
if(GBackLiquid(x, y))
SoundAt(Format("Fire::BlastLiquid%d*",grade), x, y);
else
SoundAt(Format("Fire::Blast%d*", grade), x, y);
}
// possibly init particle definitions?
if (!ExplosionParticles_Blast)
ExplosionParticles_Init();
smoothness = smoothness ?? 0;
var level_pow = level ** 2;
var level_pow_fraction = Max(level_pow / 25, 5 * level);
var wilderness_level = level * (100 - smoothness) / 100;
var smoothness_level = level * smoothness / 100;
var smoke_size = PV_KeyFrames(0, 180, level, 1000, level * 2);
var blast_size = PV_KeyFrames(0, 0, 0, 260, level * 2, 1000, level);
var blast_smooth_size = PV_KeyFrames(0, 0, 0, 250, PV_Random(level, level * 2), 1000, level);
var star_size = PV_KeyFrames(0, 0, 0, 500, level * 2, 1000, 0);
var shockwave_size = PV_Linear(0, level * 4);
var clr = HSL(Random(255), 255, 100);
CreateParticle("SmokeDirty", PV_Random(x - 10,x + 10), PV_Random(y - 10, y + 10), 0, PV_Random(-2, 0), PV_Random(50, 100), {Prototype = Particles_Colored(ExplosionParticles_Smoke, clr), Size = smoke_size}, Max(2, wilderness_level / 10));
CreateParticle("SmokeDirty", PV_Random(x - 5, x + 5), PV_Random(y - 5, y + 5), PV_Random(-1, 1), PV_Random(-1, 1), PV_Random(20, 40), {Prototype = Particles_Colored(ExplosionParticles_BlastSmoothBackground, clr), Size = blast_smooth_size}, smoothness_level / 5);
CreateParticle("SmokeDirty", PV_Random(x - 5, x + 5), PV_Random(y - 5, y + 5), PV_Random(-1, 1), PV_Random(-1, 1), PV_Random(20, 40), {Prototype = Particles_Colored(ExplosionParticles_BlastSmooth, clr), Size = blast_smooth_size}, smoothness_level / 5);
CreateParticle("Dust", PV_Random(x - 5, x + 5), PV_Random(y - 5, y + 5), 0, 0, PV_Random(18, 25), {Prototype = Particles_Colored(ExplosionParticles_Blast, clr), Size = blast_size}, smoothness_level / 5);
CreateParticle("StarFlash", PV_Random(x - 6, x + 6), PV_Random(y - 6, y + 6), PV_Random(-wilderness_level/4, wilderness_level/4), PV_Random(-wilderness_level/4, wilderness_level/4), PV_Random(10, 12), {Prototype = Particles_Colored(ExplosionParticles_Star, clr), Size = star_size}, wilderness_level / 3);
CreateParticle("Shockwave", x, y, 0, 0, 15, {Prototype = Particles_Colored(ExplosionParticles_Shockwave, clr), Size = shockwave_size}, nil);
// cast either some sparks on land or bubbles under water
if(GBackLiquid(x, y) && Global.CastBubbles)
{
Global->CastBubbles(level * 7 / 10, level, x, y);
}
else
{
CreateParticle("Magic", PV_Random(x - 5, x + 5), PV_Random(y - 5, y + 5), PV_Random(-level_pow_fraction, level_pow_fraction), PV_Random(-level_pow_fraction, level_pow_fraction), PV_Random(25, 70), Particles_Colored(ExplosionParticles_Glimmer, clr), level);
}
// very wild explosion? Smoke trails!
var smoke_trail_count = wilderness_level / 10;
var angle = Random(360);
var failsafe = 0; // against infinite loops
while (smoke_trail_count > 0 && (++failsafe < smoke_trail_count * 10))
{
angle += RandomX(40, 80);
var smokex = Sin(angle, RandomX(level / 4, level / 2));
var smokey = -Cos(angle, RandomX(level / 4, level / 2));
if (GBackSolid(x + smokex, y + smokey))
continue;
var lvl = 2 * wilderness_level;
CreateSmokeTrail(lvl, angle, x + smokex, y + smokey, clr);
smoke_trail_count--;
}
// Temporary light effect
if (level > 5)
Global->CreateLight(x, y, level, Fx_Light.LGT_Blast);
return;
}
global func FxSmokeTrailStart(object target, proplist e, int temp, int color)
{
if (g_theme != MiamiIce) return inherited(target, e, temp, color, ...);
if (temp)
return;
e.color = color ?? RGBa(255, 128, 0, 200);
var c = SplitRGBaValue(color);
var alpha = (e.color >> 24) & 0xff;
e.particles_smoke =
{
R = c.R,
G = c.G,
B = c.B,
Alpha = PV_KeyFrames(0, 0, alpha/4, 200, alpha, 1000, 0),
Rotation = PV_Random(-45,45),
ForceX = PV_Wind(20),
ForceY = PV_Gravity(-10),
};
e.particles_blast =
{
R = PV_Linear((e.color >> 16) & 0xff, 0),
G = PV_Linear((e.color >> 8) & 0xff, 0),
B = PV_Linear((e.color >> 0) & 0xff, 0),
Alpha = PV_KeyFrames(0, 0, alpha, 500, 3*alpha/4, 1000, 0),
Rotation = PV_Direction(),
BlitMode = GFX_BLIT_Additive,
Stretch = PV_Speed(1500, 1000)
};
}

View File

@ -0,0 +1,22 @@
#appendto IronBomb
public func FxFuseBurnTimer(object target, effect fx, int time)
{
if (g_theme != MiamiIce) return inherited(target, fx, time, ...);
if(!fx.clr)
fx.clr = HSL(Random(255), 255, 100);
// Emit some smoke from the fuse hole.
var i = 3;
var x = +Sin(GetR(), i);
var y = -Cos(GetR(), i);
CreateParticle("Smoke", x, y, x, y, PV_Random(18, 36), Particles_Colored(Particles_Smoke(), fx.clr), 2);
// Explode if time is up.
if (time >= FuseTime())
{
DoExplode();
return FX_Execute_Kill;
}
return FX_OK;
}

View File

@ -0,0 +1,33 @@
#appendto WindBag
public func FxIntBurstWindStart(object target, proplist effect, int temp, object clonk, int x, int y)
{
if (g_theme != MiamiIce) return inherited(target, effect, temp, clonk, x, y, ...);
if (temp)
return FX_OK;
effect.Interval = 1;
effect.clonk = clonk;
effect.x = clonk->GetX();
effect.y = clonk->GetY();
effect.angle = Angle(0, 0, x, y);
// Sound effect.
Sound("Objects::Windbag::Gust");
// Particle effect.
var clr = HSL(Random(255), 255, 100);
for (var dr = 12; dr < 32; dr++)
{
var r = RandomX(-20, 20);
var sx = Sin(effect.angle + r, dr / 2);
var sy = -Cos(effect.angle + r, dr / 2);
var vx = Sin(effect.angle + r, 2 * fill_amount / 3 + 12);
var vy = -Cos(effect.angle + r, 2 * fill_amount / 3 + 12);
if (!GBackSolid(sx, sy))
CreateParticle("Air", sx, sy, vx, vy, 36, Particles_Colored(Particles_Air(), clr));
}
// Make a timer call for the instant movement effect.
FxIntBurstWindTimer(target, effect, 0);
return FX_OK;
}