diff --git a/docs/sdk/script/fn/CanInsertMaterial.xml b/docs/sdk/script/fn/CanInsertMaterial.xml index 6c7a21e88..6fe2bfd85 100644 --- a/docs/sdk/script/fn/CanInsertMaterial.xml +++ b/docs/sdk/script/fn/CanInsertMaterial.xml @@ -1,46 +1,46 @@ - - - - - - CanInsertMaterial - Landscape - Material - 5.4 OC - - bool - - - int - material_index - Material to test to be inserted (see Material()). - - - int - x - X insert position or offset - - - - int - y - Y insert position or offset - - - - proplist - out_insertpos - If a writeable proplist is passed, members x and y are filled with the position at which the material would be inserted. - - - - - Tests if a material pixel at the given position can be inserted. - If the target position already contains material of the same density as the inserted material, the engine will search upwards for a proper insertion position. - - Material - - - Sven22001-11 - + + + + + + CanInsertMaterial + Landscape + Material + 5.4 OC + + bool + + + int + material_index + Material to test to be inserted (see Material()). + + + int + x + X insert position or offset + + + + int + y + Y insert position or offset + + + + proplist + out_insertpos + If a writeable proplist is passed, members x and y are filled with the position at which the material would be inserted. + + + + + Tests if a material pixel at the given position can be inserted. + If the target position already contains material of the same density as the inserted material, the engine will search upwards for a proper insertion position. + + Material + + + Sven22001-11 + diff --git a/planet/Defense.ocf/FightForGidl.ocs/CustomAI.ocd/Script.c b/planet/Defense.ocf/FightForGidl.ocs/CustomAI.ocd/Script.c index dc7502946..e22fd182e 100644 --- a/planet/Defense.ocf/FightForGidl.ocs/CustomAI.ocd/Script.c +++ b/planet/Defense.ocf/FightForGidl.ocs/CustomAI.ocd/Script.c @@ -1,215 +1,215 @@ -#include AI - -public func SetEnemyData(object clonk, proplist data) -{ - var fx = clonk->~GetAI(); - if (fx) - { - if (data.Siege) - fx.is_siege = true; - return true; - } - return false; -} - -public func FindTarget(effect fx) -{ - // Attack doors and statue unless an enemy clonk is closer than these objectives - var objective; - if (g_doorleft && fx.Target->GetX() <= g_doorleft->GetX() + 5) - objective = g_doorleft.dummy_target; - else if (g_doorright && fx.Target->GetX() >= g_doorright->GetX()-5) - objective = g_doorright.dummy_target; - else - objective = g_statue; - var target = inherited(fx, ...); - if (objective) - if (fx.is_siege || !target || fx.Target->ObjectDistance(target) > fx.Target->ObjectDistance(objective)) - target = objective; - return target; -} - -private func CheckVehicleAmmo(effect fx, object catapult) -{ - // Ammo is auto-refilled - return true; -} - -private func ExecuteBomber(effect fx) -{ - // Still carrying the bomb? - if (fx.weapon->Contained() != fx.Target) - { - fx.weapon=nil; - return false; - } - // Are we in range? - if (fx.Target->ObjectDistance(fx.target) < 20) - { - // Suicide! - fx.weapon->GoBoom(); - fx.Target->Kill(); - } - else - { - // Not in range. Walk there. - if (!fx.Target->GetCommand() || !Random(10)) - fx.Target->SetCommand("MoveTo", fx.target); - } - return true; -} - -func Execute(effect fx, int time) -{ - // Execution: No defensive AI. All enemies move towards target - var target = fx.target ?? g_statue; - if (!Random(10) && target) - { - var tx = target->GetX(); - if (Abs(tx-fx.Target->GetX())>30) - { - fx.Target->SetCommand("MoveTo", nil, BoundBy(fx.Target->GetX(), tx - 30, tx + 30), target->GetY()); - return true; - } - } - return inherited(fx, time, ...); -} - -func ExecuteIdle(effect fx) -{ - // Idle execution overridden by Execute - return true; -} - - -//====================================================================== -/* Enemy creation */ - -func Departure_WeaponRespawn(object container) -{ - // Weapon used? Schedule to respawn a new one! - if (container->GetAlive() || container->GetID()==Catapult) container->ScheduleCall(container, CustomAI.DoWeaponRespawn, 5, 1, GetID()); - this.Departure = nil; -} - -func DoWeaponRespawn(id_weapon) -{ - if (GetAlive() || GetID()==Catapult) - { - var re_weapon = CreateContents(id_weapon); - if (re_weapon) re_weapon.Departure = CustomAI.Departure_WeaponRespawn; - return re_weapon; - } -} - -func Inventory_GetCarryTransform() -{ - if (GetID().GetCarryTransform) - return Trans_Mul(Call(GetID().GetCarryTransform, ...), this.ExtraTransform); - else - return this.ExtraTransform; -} - -func LaunchEnemy(proplist enemy, int xmin, int xrange, int y) -{ - // Create enemy (usually a Clonk) - var x = xmin+Random(xrange); - var obj = CreateObjectAbove(enemy.Type ?? Clonk, x,y, ENEMY), clonk; - if (!obj) return nil; - obj->SetController(ENEMY); - obj->MakeCrewMember(ENEMY); - // Enemy visuals - if (enemy.Skin) - { - if (GetType(enemy.Skin) == C4V_Array) - { - obj->SetSkin(enemy.Skin[0]); - obj->SetMeshMaterial(enemy.Skin[1]); - } - else - obj->SetSkin(enemy.Skin); - } - if (GetType(enemy.Backpack)) obj->~RemoveBackpack(); - if (enemy.Scale) obj->SetMeshTransformation(Trans_Scale(enemy.Scale[0], enemy.Scale[1], enemy.Scale[2]), CLONK_MESH_TRANSFORM_SLOT_Scale); - if (enemy.Name) obj->SetName(enemy.Name); - obj->SetColor(enemy.Color); - // Physical properties - obj.MaxEnergy = (enemy.Energy ?? 50) * 1000; - obj->DoEnergy(10000); - if (enemy.Speed) - { - // Speed: Modify Speed in all ActMap entries - if (obj.ActMap == obj.Prototype.ActMap) obj.ActMap = new obj.ActMap {}; - for (var action in /*obj.ActMap->GetProperties()*/ ["Walk", "Scale", "Dig", "Swim", "Hangle", "Jump", "WallJump", "Dive", "Push"]) // obj.ActMap->GetProperties() doesn't work :( - { - if (action == "Prototype") continue; - if (obj.ActMap[action] == obj.Prototype.ActMap[action]) obj.ActMap[action] = new obj.ActMap[action] {}; - obj.ActMap[action].Speed = obj.ActMap[action].Speed * enemy.Speed / 100; - } - obj.JumpSpeed = obj.JumpSpeed * enemy.Speed / 100; - obj.FlySpeed = obj.FlySpeed * enemy.Speed / 100; - } - obj.MaxContentsCount = 1; - // Reward for killing enemy - obj.Bounty = enemy.Bounty; - // Vehicles - var vehicle; - if (enemy.Vehicle) - { - vehicle = CreateObjectAbove(enemy.Vehicle, x,y); - obj->SetAction("Push", vehicle); - } - // Enemy inventory - if (enemy.Inventory) for (var inv in ForceVal2Array(enemy.Inventory)) - { - var inv_type = inv.InvType; - if (!inv_type) inv_type = inv; - var inv_obj = obj->CreateContents(inv_type); - if (inv_obj) - { - // Marker for custom weapon behaviour - inv_obj.IsAIWeapon = true; - // Infinite ammo - inv_obj->~SetInfiniteStackCount(); - if (GetIndexOf(g_respawning_weapons, inv_type) >= 0) inv_obj.Departure = CustomAI.Departure_WeaponRespawn; - // Extra settings? - if (inv.InvType) - { - // Visuals - if (inv.Scale) { inv_obj.GetCarryTransform = CustomAI.Inventory_GetCarryTransform; inv_obj.ExtraTransform = Trans_Scale(inv.Scale, inv.Scale, inv.Scale); } - if (inv.Material) inv_obj->SetMeshMaterial(inv.Material); - // Strength - if (inv.Strength) inv_obj->SetStrength(inv.Strength); - } - } - } - // Flying AI - if (obj->~HasNoNeedForAI()) - { - // Flying enemies all init themselves to fly at the statue at the moment - } - else - { - // Init AI: Run towards statue - CustomAI->AddAI(obj); - CustomAI->SetMaxAggroDistance(obj, LandscapeWidth()); - var fx = obj.ai; - if (fx) fx.vehicle = vehicle; - if (g_statue) - { - CustomAI->SetHome(obj, g_statue->GetX(), g_statue->GetY(), Random(2)); - CustomAI->SetGuardRange(obj, 0,0,LandscapeWidth(),LandscapeHeight()); // nowhere to run! - CustomAI->SetEnemyData(obj, enemy); - // CustomAI->SetGuardRange(obj, g_statue->GetX()-200, g_statue->GetY()-50, 400, 100); - } - } - // Remember this clonk to end wave when all enemies have been killed - g_spawned_enemies[GetLength(g_spawned_enemies)] = obj; - return obj; -} - -// helper: put single elements into array -// -global func ForceVal2Array(v) { if (GetType(v) != C4V_Array) return [v]; else return v; } - - +#include AI + +public func SetEnemyData(object clonk, proplist data) +{ + var fx = clonk->~GetAI(); + if (fx) + { + if (data.Siege) + fx.is_siege = true; + return true; + } + return false; +} + +public func FindTarget(effect fx) +{ + // Attack doors and statue unless an enemy clonk is closer than these objectives + var objective; + if (g_doorleft && fx.Target->GetX() <= g_doorleft->GetX() + 5) + objective = g_doorleft.dummy_target; + else if (g_doorright && fx.Target->GetX() >= g_doorright->GetX()-5) + objective = g_doorright.dummy_target; + else + objective = g_statue; + var target = inherited(fx, ...); + if (objective) + if (fx.is_siege || !target || fx.Target->ObjectDistance(target) > fx.Target->ObjectDistance(objective)) + target = objective; + return target; +} + +private func CheckVehicleAmmo(effect fx, object catapult) +{ + // Ammo is auto-refilled + return true; +} + +private func ExecuteBomber(effect fx) +{ + // Still carrying the bomb? + if (fx.weapon->Contained() != fx.Target) + { + fx.weapon=nil; + return false; + } + // Are we in range? + if (fx.Target->ObjectDistance(fx.target) < 20) + { + // Suicide! + fx.weapon->GoBoom(); + fx.Target->Kill(); + } + else + { + // Not in range. Walk there. + if (!fx.Target->GetCommand() || !Random(10)) + fx.Target->SetCommand("MoveTo", fx.target); + } + return true; +} + +func Execute(effect fx, int time) +{ + // Execution: No defensive AI. All enemies move towards target + var target = fx.target ?? g_statue; + if (!Random(10) && target) + { + var tx = target->GetX(); + if (Abs(tx-fx.Target->GetX())>30) + { + fx.Target->SetCommand("MoveTo", nil, BoundBy(fx.Target->GetX(), tx - 30, tx + 30), target->GetY()); + return true; + } + } + return inherited(fx, time, ...); +} + +func ExecuteIdle(effect fx) +{ + // Idle execution overridden by Execute + return true; +} + + +//====================================================================== +/* Enemy creation */ + +func Departure_WeaponRespawn(object container) +{ + // Weapon used? Schedule to respawn a new one! + if (container->GetAlive() || container->GetID()==Catapult) container->ScheduleCall(container, CustomAI.DoWeaponRespawn, 5, 1, GetID()); + this.Departure = nil; +} + +func DoWeaponRespawn(id_weapon) +{ + if (GetAlive() || GetID()==Catapult) + { + var re_weapon = CreateContents(id_weapon); + if (re_weapon) re_weapon.Departure = CustomAI.Departure_WeaponRespawn; + return re_weapon; + } +} + +func Inventory_GetCarryTransform() +{ + if (GetID().GetCarryTransform) + return Trans_Mul(Call(GetID().GetCarryTransform, ...), this.ExtraTransform); + else + return this.ExtraTransform; +} + +func LaunchEnemy(proplist enemy, int xmin, int xrange, int y) +{ + // Create enemy (usually a Clonk) + var x = xmin+Random(xrange); + var obj = CreateObjectAbove(enemy.Type ?? Clonk, x,y, ENEMY), clonk; + if (!obj) return nil; + obj->SetController(ENEMY); + obj->MakeCrewMember(ENEMY); + // Enemy visuals + if (enemy.Skin) + { + if (GetType(enemy.Skin) == C4V_Array) + { + obj->SetSkin(enemy.Skin[0]); + obj->SetMeshMaterial(enemy.Skin[1]); + } + else + obj->SetSkin(enemy.Skin); + } + if (GetType(enemy.Backpack)) obj->~RemoveBackpack(); + if (enemy.Scale) obj->SetMeshTransformation(Trans_Scale(enemy.Scale[0], enemy.Scale[1], enemy.Scale[2]), CLONK_MESH_TRANSFORM_SLOT_Scale); + if (enemy.Name) obj->SetName(enemy.Name); + obj->SetColor(enemy.Color); + // Physical properties + obj.MaxEnergy = (enemy.Energy ?? 50) * 1000; + obj->DoEnergy(10000); + if (enemy.Speed) + { + // Speed: Modify Speed in all ActMap entries + if (obj.ActMap == obj.Prototype.ActMap) obj.ActMap = new obj.ActMap {}; + for (var action in /*obj.ActMap->GetProperties()*/ ["Walk", "Scale", "Dig", "Swim", "Hangle", "Jump", "WallJump", "Dive", "Push"]) // obj.ActMap->GetProperties() doesn't work :( + { + if (action == "Prototype") continue; + if (obj.ActMap[action] == obj.Prototype.ActMap[action]) obj.ActMap[action] = new obj.ActMap[action] {}; + obj.ActMap[action].Speed = obj.ActMap[action].Speed * enemy.Speed / 100; + } + obj.JumpSpeed = obj.JumpSpeed * enemy.Speed / 100; + obj.FlySpeed = obj.FlySpeed * enemy.Speed / 100; + } + obj.MaxContentsCount = 1; + // Reward for killing enemy + obj.Bounty = enemy.Bounty; + // Vehicles + var vehicle; + if (enemy.Vehicle) + { + vehicle = CreateObjectAbove(enemy.Vehicle, x,y); + obj->SetAction("Push", vehicle); + } + // Enemy inventory + if (enemy.Inventory) for (var inv in ForceVal2Array(enemy.Inventory)) + { + var inv_type = inv.InvType; + if (!inv_type) inv_type = inv; + var inv_obj = obj->CreateContents(inv_type); + if (inv_obj) + { + // Marker for custom weapon behaviour + inv_obj.IsAIWeapon = true; + // Infinite ammo + inv_obj->~SetInfiniteStackCount(); + if (GetIndexOf(g_respawning_weapons, inv_type) >= 0) inv_obj.Departure = CustomAI.Departure_WeaponRespawn; + // Extra settings? + if (inv.InvType) + { + // Visuals + if (inv.Scale) { inv_obj.GetCarryTransform = CustomAI.Inventory_GetCarryTransform; inv_obj.ExtraTransform = Trans_Scale(inv.Scale, inv.Scale, inv.Scale); } + if (inv.Material) inv_obj->SetMeshMaterial(inv.Material); + // Strength + if (inv.Strength) inv_obj->SetStrength(inv.Strength); + } + } + } + // Flying AI + if (obj->~HasNoNeedForAI()) + { + // Flying enemies all init themselves to fly at the statue at the moment + } + else + { + // Init AI: Run towards statue + CustomAI->AddAI(obj); + CustomAI->SetMaxAggroDistance(obj, LandscapeWidth()); + var fx = obj.ai; + if (fx) fx.vehicle = vehicle; + if (g_statue) + { + CustomAI->SetHome(obj, g_statue->GetX(), g_statue->GetY(), Random(2)); + CustomAI->SetGuardRange(obj, 0,0,LandscapeWidth(),LandscapeHeight()); // nowhere to run! + CustomAI->SetEnemyData(obj, enemy); + // CustomAI->SetGuardRange(obj, g_statue->GetX()-200, g_statue->GetY()-50, 400, 100); + } + } + // Remember this clonk to end wave when all enemies have been killed + g_spawned_enemies[GetLength(g_spawned_enemies)] = obj; + return obj; +} + +// helper: put single elements into array +// +global func ForceVal2Array(v) { if (GetType(v) != C4V_Array) return [v]; else return v; } + +