Initial commit: OpenRA game engine
Some checks failed
Continuous Integration / Linux (.NET 8.0) (push) Has been cancelled
Continuous Integration / Windows (.NET 8.0) (push) Has been cancelled

Fork from OpenRA/OpenRA with one-click launch script (start-ra.cmd)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
let5sne.win10
2026-01-10 21:46:54 +08:00
commit 9cf6ebb986
4065 changed files with 635973 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
--[[
Copyright (c) The OpenRA Developers and Contributors
This file is part of OpenRA, which is free software. It is made
available to you under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. For more
information, see COPYING.
]]
AttackGroupSize =
{
easy = 6,
normal = 8,
hard = 10
}
AttackDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
hard = { DateTime.Seconds(1), DateTime.Seconds(3) }
}
HarkonnenInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
HarkonnenTankType = { "combat_tank_h" }
-- Overwrite the template function because of the message
SendAttack = function(owner, size)
if Attacking[owner] then
return
end
Attacking[owner] = true
HoldProduction[owner] = true
local units = SetupAttackGroup(owner, size)
Utils.Do(units, IdleHunt)
if #units > 0 then
Media.DisplayMessage(UserInterface.GetFluentMessage("harkonnen-units-approaching"), UserInterface.GetFluentMessage("fremen-leader"))
end
Trigger.OnAllRemovedFromWorld(units, function()
Attacking[owner] = false
HoldProduction[owner] = false
end)
end
InitAIUnits = function()
IdlingUnits[Harkonnen] = Reinforcements.Reinforce(Harkonnen, InitialHarkonnenReinforcements, HarkonnenPaths[1])
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
end
ActivateAI = function()
LastHarvesterEaten[Harkonnen] = true
InitAIUnits()
FremenProduction()
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end
local tanksToBuild = function() return HarkonnenTankType end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(Harkonnen, HarkonnenBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Harkonnen, HarkonnenHeavyFact, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end

View File

@@ -0,0 +1,220 @@
--[[
Copyright (c) The OpenRA Developers and Contributors
This file is part of OpenRA, which is free software. It is made
available to you under the terms of the GNU General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version. For more
information, see COPYING.
]]
HarkonnenBase = { HarkonnenOutpost, HarkonnenRefinery, HarkonnenHeavyFact, HarkonnenTurret1, HarkonnenTurret2, HarkonnenBarracks, HarkonnenSilo1, HarkonnenSilo2, HarkonnenWindTrap1, HarkonnenWindTrap2, HarkonnenWindTrap3, HarkonnenWindTrap4, HarkonnenWindTrap5 }
HarkonnenReinforcements =
{
easy =
{
{ "combat_tank_h", "trooper", "trooper", "trooper", "trooper" },
{ "trooper", "trooper", "trooper", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper" }
},
normal =
{
{ "combat_tank_h", "trooper", "trooper", "trooper", "trooper" },
{ "trooper", "trooper", "trooper", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "combat_tank_h", "light_inf", "trooper", "trooper", "quad" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad" }
},
hard =
{
{ "combat_tank_h", "trooper", "trooper", "trooper", "trooper" },
{ "trooper", "trooper", "trooper", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "light_inf", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper" },
{ "combat_tank_h", "trike", "combat_tank_h", "light_inf", "trooper", "trooper", "quad" },
{ "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad" },
{ "combat_tank_h", "combat_tank_h", "trike", "light_inf", "light_inf", "trooper", "trooper", "quad", "quad" },
{ "combat_tank_h", "combat_tank_h", "combat_tank_h", "combat_tank_h", "combat_tank_h", "combat_tank_h" }
}
}
HarkonnenAttackDelay =
{
easy = DateTime.Minutes(3),
normal = DateTime.Minutes(2) + DateTime.Seconds(20),
hard = DateTime.Minutes(1)
}
HarkonnenAttackWaves =
{
easy = 5,
normal = 7,
hard = 9
}
InitialHarkonnenReinforcements = { "trooper", "trooper", "trooper", "trooper", "trooper", "trooper" }
HarkonnenPaths =
{
{ HarkonnenEntry1.Location, HarkonnenRally3.Location },
{ HarkonnenEntry2.Location, HarkonnenRally2.Location },
{ HarkonnenEntry3.Location, HarkonnenRally4.Location },
{ HarkonnenEntry4.Location, HarkonnenRally4.Location }
}
AtreidesReinforcements =
{
{ "trike", "combat_tank_a", "combat_tank_a" },
{ "quad", "combat_tank_a", "combat_tank_a" }
}
AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location }
FremenInterval =
{
easy = { DateTime.Minutes(1) + DateTime.Seconds(30), DateTime.Minutes(2) },
normal = { DateTime.Minutes(2) + DateTime.Seconds(20), DateTime.Minutes(2) + DateTime.Seconds(40) },
hard = { DateTime.Minutes(3) + DateTime.Seconds(40), DateTime.Minutes(4) }
}
IntegrityLevel =
{
easy = 50,
normal = 75,
hard = 100
}
FremenProduction = function()
if Sietch.IsDead then
return
end
local delay = Utils.RandomInteger(FremenInterval[Difficulty][1], FremenInterval[Difficulty][2] + 1)
Fremen.Build({ "nsfremen" }, function()
Trigger.AfterDelay(delay, FremenProduction)
end)
end
AttackNotifier = 0
Tick = function()
if Atreides.HasNoRequiredUnits() then
Harkonnen.MarkCompletedObjective(KillAtreides)
end
if Harkonnen.HasNoRequiredUnits() and not Atreides.IsObjectiveCompleted(KillHarkonnen) then
Media.DisplayMessage(UserInterface.GetFluentMessage("harkonnen-annihilated"), Mentat)
Atreides.MarkCompletedObjective(KillHarkonnen)
Atreides.MarkCompletedObjective(ProtectFremen)
Atreides.MarkCompletedObjective(KeepIntegrity)
end
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[Harkonnen] then
local units = Harkonnen.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[Harkonnen] = false
ProtectHarvester(units[1], Harkonnen, AttackGroupSize[Difficulty])
end
end
if not Sietch.IsDead then
AttackNotifier = AttackNotifier - 1
local integrity = math.floor((Sietch.Health * 100) / Sietch.MaxHealth)
SiegeIntegrity = UserInterface.GetFluentMessage("sietch-integrity", { ["integrity"] = integrity })
UserInterface.SetMissionText(SiegeIntegrity, Atreides.Color)
if integrity < IntegrityLevel[Difficulty] then
Atreides.MarkFailedObjective(KeepIntegrity)
end
end
end
WorldLoaded = function()
Harkonnen = Player.GetPlayer("Harkonnen")
Fremen = Player.GetPlayer("Fremen")
Atreides = Player.GetPlayer("Atreides")
InitObjectives(Atreides)
KillAtreides = AddPrimaryObjective(Harkonnen, "")
ProtectFremen = AddPrimaryObjective(Atreides, "protect-fremen-sietch")
KillHarkonnen = AddPrimaryObjective(Atreides, "destroy-harkonnen")
local keepSietchIntact = UserInterface.GetFluentMessage("keep-sietch-intact", { ["integrity"] = IntegrityLevel[Difficulty] })
KeepIntegrity = AddPrimaryObjective(Atreides, keepSietchIntact)
Camera.Position = AConyard.CenterPosition
HarkonnenAttackLocation = AConyard.Location
Trigger.AfterDelay(DateTime.Seconds(2), function()
Beacon.New(Atreides, Sietch.CenterPosition + WVec.New(0, 1024, 0))
Media.DisplayMessage(UserInterface.GetFluentMessage("fremen-sietch-southeast"), Mentat)
end)
Trigger.OnAllKilledOrCaptured(HarkonnenBase, function()
Utils.Do(Harkonnen.GetGroundAttackers(), IdleHunt)
end)
Trigger.OnKilled(Sietch, function()
Actor.Create("invisibleBlocker", true, { Owner = Fremen, Location = CPos.New(62, 59) })
UserInterface.SetMissionText(UserInterface.GetFluentMessage("sietch-destroyed"), Atreides.Color)
Atreides.MarkFailedObjective(ProtectFremen)
end)
Trigger.OnDamaged(Sietch, function()
if AttackNotifier <= 0 then
AttackNotifier = DateTime.Seconds(10)
Beacon.New(Atreides, Sietch.CenterPosition + WVec.New(0, 1024, 0), DateTime.Seconds(7))
Media.DisplayMessage(UserInterface.GetFluentMessage("fremen-sietch-under-attack"), Mentat)
local defenders = Fremen.GetGroundAttackers()
if #defenders > 0 then
Utils.Do(defenders, function(unit)
unit.Guard(Sietch)
end)
end
end
end)
local path = function() return Utils.Random(HarkonnenPaths) end
local waveCondition = function() return Atreides.IsObjectiveCompleted(KillHarkonnen) end
local huntFunction = function(unit)
unit.AttackMove(HarkonnenAttackLocation)
IdleHunt(unit)
end
SendCarryallReinforcements(Harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty], waveCondition, huntFunction)
Actor.Create("upgrade.barracks", true, { Owner = Harkonnen })
Trigger.AfterDelay(0, ActivateAI)
Trigger.AfterDelay(DateTime.Seconds(50), function()
Media.PlaySpeechNotification(Atreides, "Reinforce")
Reinforcements.Reinforce(Atreides, AtreidesReinforcements[1], AtreidesPath)
end)
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(40), function()
Media.PlaySpeechNotification(Atreides, "Reinforce")
Reinforcements.ReinforceWithTransport(Atreides, "carryall.reinforce", AtreidesReinforcements[2], AtreidesPath, { AtreidesPath[1] })
end)
Trigger.OnEnteredProximityTrigger(HarkonnenRally1.CenterPosition, WDist.New(6 * 1024), function(a, id)
if a.Owner == Atreides then
Trigger.RemoveProximityTrigger(id)
local units = Reinforcements.Reinforce(Harkonnen, { "light_inf", "combat_tank_h", "trike" }, HarkonnenPaths[1])
Utils.Do(units, IdleHunt)
end
end)
Trigger.OnExitedProximityTrigger(Sietch.CenterPosition, WDist.New(10.5 * 1024), function(a, id)
if a.Owner == Fremen and not a.IsDead then
a.AttackMove(FremenRally.Location)
Trigger.OnIdle(a, function()
if a.Location.X < 54 or a.Location.Y < 54 then
a.AttackMove(FremenRally.Location)
end
end)
end
end)
end

Binary file not shown.

View File

@@ -0,0 +1,7 @@
## rules.yaml
briefing =
Our scouts have discovered the hidden Fremen base. The Harkonnen blockade of the Fremen must be broken.
Powerful Harkonnen forces to the South are massing for an assault on the Fremen. Heavy forces have been allocated to you to smash through the Harkonnen fortifications and come to the aid of the Fremen.
Good luck.

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

View File

@@ -0,0 +1,422 @@
MapFormat: 12
RequiresMod: d2k
Title: Atreides 04
Author: Westwood Studios
Tileset: ARRAKIS
MapSize: 68,68
Bounds: 2,2,64,64
Visibility: MissionSelector
Categories: Campaign
LockPreview: True
Players:
PlayerReference@Neutral:
Name: Neutral
OwnsWorld: True
NonCombatant: True
Faction: Random
PlayerReference@Creeps:
Name: Creeps
NonCombatant: True
Faction: Random
Enemies: Atreides, Harkonnen, Fremen
PlayerReference@Atreides:
Name: Atreides
Playable: True
LockFaction: True
Faction: atreides
LockColor: True
Color: 5A7394
Allies: Fremen
Enemies: Harkonnen, Creeps
PlayerReference@Harkonnen:
Name: Harkonnen
LockFaction: True
Faction: harkonnen
LockColor: True
Color: D64A42
Enemies: Atreides, Creeps, Fremen
Bot: campaign
PlayerReference@Fremen:
Name: Fremen
LockFaction: True
Faction: fremen
LockColor: True
Color: 848484
Allies: Atreides
Enemies: Harkonnen, Creeps
Bot: campaign
Actors:
Actor0: wormspawner
Location: 63,7
Owner: Creeps
Actor1: trike
Location: 17,11
Owner: Harkonnen
Actor2: spicebloom
Location: 20,12
Owner: Neutral
Actor3: spicebloom
Location: 24,14
Owner: Neutral
Actor4: spicebloom
Location: 40,22
Owner: Neutral
Actor5: spicebloom
Location: 57,24
Owner: Neutral
Actor6: trike
Location: 6,25
Owner: Atreides
Actor7: trike
Location: 10,26
Owner: Atreides
Actor9: combat_tank_a
Location: 10,29
Owner: Atreides
Actor10: combat_tank_a
Location: 12,29
Owner: Atreides
Actor11: spicebloom
Location: 46,29
Owner: Neutral
Actor12: light_inf
Location: 6,30
Owner: Atreides
Actor13: quad
Location: 8,30
Owner: Atreides
Actor14: light_inf
Location: 10,30
Owner: Atreides
Actor15: light_inf
Location: 4,31
Owner: Atreides
Actor16: combat_tank_a
Location: 11,31
Owner: Atreides
Actor17: combat_tank_a
Location: 9,32
Owner: Atreides
Actor18: combat_tank_a
Location: 10,32
Owner: Atreides
Actor19: combat_tank_a
Location: 8,33
Owner: Atreides
Actor20: light_inf
Location: 35,33
Owner: Harkonnen
Actor21: light_inf
Location: 33,34
Owner: Harkonnen
Actor22: spicebloom
Location: 59,34
Owner: Neutral
Actor23: wall
Location: 42,35
Owner: Harkonnen
Actor24: wall
Location: 43,35
Owner: Harkonnen
Actor25: wall
Location: 44,35
Owner: Harkonnen
Actor26: wall
Location: 45,35
Owner: Harkonnen
Actor28: wall
Location: 46,36
Owner: Harkonnen
Actor29: wall
Location: 46,37
Owner: Harkonnen
Actor30: trooper
Location: 63,39
Owner: Harkonnen
Actor31: trooper
Location: 51,40
Owner: Harkonnen
Actor32: trooper
Location: 60,41
Owner: Harkonnen
Actor35: light_inf
Location: 56,42
Owner: Harkonnen
Actor37: light_inf
Location: 54,43
Owner: Harkonnen
Actor38: wall
Location: 57,44
Owner: Harkonnen
Actor39: wall
Location: 58,44
Owner: Harkonnen
Actor40: wall
Location: 59,44
Owner: Harkonnen
Actor41: wall
Location: 60,44
Owner: Harkonnen
Actor42: wall
Location: 61,44
Owner: Harkonnen
Actor43: wall
Location: 62,44
Owner: Harkonnen
Actor44: wall
Location: 63,44
Owner: Harkonnen
Actor45: wall
Location: 64,44
Owner: Harkonnen
Actor46: wall
Location: 65,44
Owner: Harkonnen
Actor47: wall
Location: 52,45
Owner: Harkonnen
Actor48: wall
Location: 53,45
Owner: Harkonnen
Actor49: wall
Location: 54,45
Owner: Harkonnen
Actor50: wall
Location: 55,45
Owner: Harkonnen
Actor51: wall
Location: 56,45
Owner: Harkonnen
Actor52: wall
Location: 57,45
Owner: Harkonnen
Actor55: wall
Location: 35,48
Owner: Harkonnen
Actor56: wall
Location: 35,49
Owner: Harkonnen
Actor58: wall
Location: 35,50
Owner: Harkonnen
Actor61: wall
Location: 46,50
Owner: Harkonnen
Actor64: wall
Location: 46,51
Owner: Harkonnen
Actor65: nsfremen
Location: 59,51
Owner: Fremen
Actor66: nsfremen
Location: 64,51
Owner: Fremen
Actor67: trike
Location: 23,52
Owner: Harkonnen
Actor68: wall
Location: 46,52
Owner: Harkonnen
Actor69: nsfremen
Location: 60,52
Owner: Fremen
Actor70: nsfremen
Location: 62,52
Owner: Fremen
Actor71: wall
Location: 46,53
Owner: Harkonnen
Actor72: nsfremen
Location: 63,53
Owner: Fremen
Actor73: wall
Location: 46,54
Owner: Harkonnen
Actor74: nsfremen
Location: 56,54
Owner: Fremen
Actor75: nsfremen
Location: 57,54
Owner: Fremen
Actor76: nsfremen
Location: 64,54
Owner: Fremen
Actor77: wind_trap
Location: 40,55
Owner: Harkonnen
Actor80: wall
Location: 46,55
Owner: Harkonnen
Actor81: nsfremen
Location: 55,55
Owner: Fremen
Actor82: wall
Location: 36,56
Owner: Harkonnen
Actor83: wall
Location: 46,56
Owner: Harkonnen
Actor84: nsfremen
Location: 55,56
Owner: Fremen
Actor85: wall
Location: 36,57
Owner: Harkonnen
Actor86: wall
Location: 46,57
Owner: Harkonnen
Actor87: nsfremen
Location: 57,57
Owner: Fremen
Actor88: nsfremen
Location: 60,57
Owner: Fremen
Actor89: nsfremen
Location: 64,57
Owner: Fremen
Actor90: wall
Location: 36,58
Owner: Harkonnen
Actor91: wall
Location: 37,58
Owner: Harkonnen
Actor92: wall
Location: 38,58
Owner: Harkonnen
Actor93: wall
Location: 39,58
Owner: Harkonnen
Actor94: wall
Location: 40,58
Owner: Harkonnen
Actor95: wall
Location: 41,58
Owner: Harkonnen
Actor96: wall
Location: 42,58
Owner: Harkonnen
Actor97: wall
Location: 43,58
Owner: Harkonnen
Actor98: wall
Location: 44,58
Owner: Harkonnen
Actor99: wall
Location: 45,58
Owner: Harkonnen
Actor100: wall
Location: 46,58
Owner: Harkonnen
Actor101: nsfremen
Location: 55,59
Owner: Fremen
Actor103: spicebloom
Location: 9,60
Owner: Neutral
Actor104: nsfremen
Location: 55,61
Owner: Fremen
Actor105: nsfremen
Location: 58,62
Owner: Fremen
Actor106: nsfremen
Location: 65,63
Owner: Fremen
HarkonnenOutpost: outpost
Location: 62,41
Owner: Harkonnen
HarkonnenRefinery: refinery
Location: 43,43
Owner: Harkonnen
HarkonnenHeavyFact: heavy_factory
Location: 43,46
Owner: Harkonnen
HarkonnenTurret1: medium_gun_turret
Location: 46,35
Owner: Harkonnen
HarkonnenTurret2: medium_gun_turret
Location: 35,47
Owner: Harkonnen
HarkonnenBarracks: barracks
Location: 42,50
Owner: Harkonnen
HarkonnenSilo1: silo
Location: 39,50
Owner: Harkonnen
HarkonnenSilo2: silo
Location: 44,51
Owner: Harkonnen
HarkonnenWindTrap1: wind_trap
Location: 37,49
Owner: Harkonnen
HarkonnenWindTrap2: wind_trap
Location: 39,51
Owner: Harkonnen
HarkonnenWindTrap3: wind_trap
Location: 42,55
Owner: Harkonnen
HarkonnenWindTrap4: wind_trap
Location: 44,55
Owner: Harkonnen
HarkonnenWindTrap5: wind_trap
Location: 52,42
Owner: Harkonnen
AConyard: construction_yard
Location: 5,27
Owner: Atreides
Sietch: sietch
Location: 62,59
Owner: Fremen
HackyTile: tile475
Location: 62,59
Owner: Neutral
HarkonnenEntry1: waypoint
Owner: Neutral
Location: 65,35
HarkonnenEntry2: waypoint
Owner: Neutral
Location: 14,65
HarkonnenEntry3: waypoint
Owner: Neutral
Location: 31,2
HarkonnenEntry4: waypoint
Owner: Neutral
Location: 10,2
HarkonnenRally1: waypoint
Owner: Neutral
Location: 48,46
HarkonnenRally2: waypoint
Owner: Neutral
Location: 16,39
HarkonnenRally3: waypoint
Owner: Neutral
Location: 52,40
HarkonnenRally4: waypoint
Owner: Neutral
Location: 8,6
AtreidesEntry: waypoint
Owner: Neutral
Location: 2,18
AtreidesRally: waypoint
Owner: Neutral
Location: 5,23
FremenRally: waypoint
Owner: Neutral
Location: 56,54
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
Sequences: sequences.yaml
FluentMessages: d2k|fluent/lua.ftl, d2k|fluent/campaign.ftl, map.ftl

View File

@@ -0,0 +1,100 @@
Player:
PlayerResources:
DefaultCash: 6000
World:
LuaScript:
Scripts: campaign.lua, utils.lua, atreides04.lua, atreides04-AI.lua
MissionData:
Briefing: briefing
BriefingVideo: A_BR04_E.VQA
MapOptions:
TechLevel: low
ScriptLobbyDropdown@difficulty:
ID: difficulty
Label: dropdown-difficulty.label
Description: dropdown-difficulty.description
Values:
easy: options-difficulty.easy
normal: options-difficulty.normal
hard: options-difficulty.hard
Default: easy
carryall.reinforce:
Cargo:
MaxWeight: 10
sietch:
Exit:
ExitCell: 0,2
Production:
Produces: Infantry
nsfremen:
Buildable:
Prerequisites: ~sietch
AutoTarget:
InitialStanceAI: AttackAnything
concreteb:
Buildable:
Prerequisites: ~disabled
medium_gun_turret:
Buildable:
Prerequisites: ~disabled
outpost:
Buildable:
Prerequisites: barracks
quad:
Buildable:
Prerequisites: upgrade.light
trooper:
Buildable:
Prerequisites: upgrade.barracks
engineer:
Buildable:
Prerequisites: upgrade.barracks
repair_pad:
Buildable:
Prerequisites: heavy_factory
mcv:
Buildable:
Prerequisites: repair_pad
upgrade.conyard:
Buildable:
Prerequisites: ~disabled
upgrade.heavy:
Buildable:
Prerequisites: ~disabled
# HACK: AI units can't attack the sietch if it was on a real rock
tile475:
Immobile:
OccupiesSpace: false
RenderSprites:
Palette: d2k
WithIdleOverlay@2:
Sequence: idle2
WithIdleOverlay@3:
Sequence: idle3
WithIdleOverlay@4:
Sequence: idle4
WithSpriteBody:
BodyOrientation:
QuantizedFacings: 1
Interactable:
# Placed after the sietch is destroyed so that the cliff is still unpassable
invisibleBlocker:
Building:
Footprint: xx xx
Dimensions: 2,2

View File

@@ -0,0 +1,15 @@
tile475:
Defaults:
Filename: BLOXWAST.R16
idle:
Start: 706
Offset: -16,-16
idle2:
Start: 707
Offset: 16,-16
idle3:
Start: 726
Offset: -16,16
idle4:
Start: 727
Offset: 16,16