Allow changing animal AI of blocks

This commit is contained in:
UnknownShadow200 2017-04-30 18:27:24 +10:00
parent a977748936
commit f2fb839d02
6 changed files with 92 additions and 26 deletions

View File

@ -98,14 +98,9 @@ namespace MCGalaxy.Blocks {
/// <summary> Initalise physics handling behaviour for the core blocks. </summary>
internal static void InitCorePhysicsHandlers() {
physicsHandlers[Block.birdblack] = BirdPhysics.Do;
physicsHandlers[Block.birdwhite] = BirdPhysics.Do;
physicsHandlers[Block.birdlava] = BirdPhysics.Do;
physicsHandlers[Block.birdwater] = BirdPhysics.Do;
physicsHandlers[Block.birdred] = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.air);
physicsHandlers[Block.birdblue] = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.air);
physicsHandlers[Block.birdkill] = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.air);
for (int i = 0; i < Block.Count; i++) {
physicsHandlers[i] = null;
}
physicsHandlers[Block.snaketail] = SnakePhysics.DoTail;
physicsHandlers[Block.snake] = SnakePhysics.Do;
physicsHandlers[Block.rockethead] = RocketPhysics.Do;
@ -113,13 +108,6 @@ namespace MCGalaxy.Blocks {
physicsHandlers[Block.zombiebody] = ZombiePhysics.Do;
physicsHandlers[Block.zombiehead] = ZombiePhysics.DoHead;
physicsHandlers[Block.creeper] = ZombiePhysics.Do;
physicsHandlers[Block.fishbetta] = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.water);
physicsHandlers[Block.fishshark] = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.water);
physicsHandlers[Block.fishlavashark] = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.lava);
physicsHandlers[Block.fishgold] = (Level lvl, ref Check C) => HunterPhysics.DoFlee(lvl, ref C, Block.water);
physicsHandlers[Block.fishsalmon] = (Level lvl, ref Check C) => HunterPhysics.DoFlee(lvl, ref C, Block.water);
physicsHandlers[Block.fishsponge] = (Level lvl, ref Check C) => HunterPhysics.DoFlee(lvl, ref C, Block.water);
physicsHandlers[Block.water] = SimpleLiquidPhysics.DoWater;
physicsHandlers[Block.activedeathwater] = SimpleLiquidPhysics.DoWater;
@ -171,6 +159,9 @@ namespace MCGalaxy.Blocks {
physicsHandlers[Block.train] = TrainPhysics.Do;
for (int i = 0; i < Block.Count; i++) {
HandlePhysics animalAI = AnimalAIHandler(Block.Props[i].AnimalAI);
if (animalAI != null) { physicsHandlers[i] = animalAI; continue; }
//Adv physics updating anything placed next to water or lava
if ((i >= Block.red && i <= Block.redmushroom) || i == Block.wood ||
i == Block.trunk || i == Block.bookcase) {
@ -184,5 +175,26 @@ namespace MCGalaxy.Blocks {
}
}
}
static HandlePhysics AnimalAIHandler(AnimalAI ai) {
if (ai == AnimalAI.Fly) return BirdPhysics.Do;
if (ai == AnimalAI.FleeAir) {
return (Level lvl, ref Check C) => HunterPhysics.DoFlee(lvl, ref C, Block.air);
} else if (ai == AnimalAI.FleeWater) {
return (Level lvl, ref Check C) => HunterPhysics.DoFlee(lvl, ref C, Block.water);
} else if (ai == AnimalAI.FleeLava) {
return (Level lvl, ref Check C) => HunterPhysics.DoFlee(lvl, ref C, Block.lava);
}
if (ai == AnimalAI.KillerAir) {
return (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.air);
} else if (ai == AnimalAI.KillerWater) {
return (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.water);
} else if (ai == AnimalAI.KillerLava) {
return (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.lava);
}
return null;
}
}
}

View File

@ -85,7 +85,25 @@ namespace MCGalaxy {
Props[wood].LavaKills = true; Props[trunk].LavaKills = true;
Props[sponge].LavaKills = true; Props[bookcase].LavaKills = true;
Props[leaf].LavaKills = true; Props[crate].LavaKills = true;
Props[red].IsRails = true; Props[op_air].IsRails = true;
Props[red].IsRails = true; Props[op_air].IsRails = true;
// Block specific physics properties
Props[Block.birdblack].AnimalAI = AnimalAI.Fly;
Props[Block.birdwhite].AnimalAI = AnimalAI.Fly;
Props[Block.birdlava].AnimalAI = AnimalAI.Fly;
Props[Block.birdwater].AnimalAI = AnimalAI.Fly;
Props[Block.birdred].AnimalAI = AnimalAI.KillerAir;
Props[Block.birdblue].AnimalAI = AnimalAI.KillerAir;
Props[Block.birdkill].AnimalAI = AnimalAI.KillerAir;
Props[Block.fishbetta].AnimalAI = AnimalAI.KillerWater;
Props[Block.fishshark].AnimalAI = AnimalAI.KillerWater;
Props[Block.fishlavashark].AnimalAI = AnimalAI.KillerLava;
Props[Block.fishgold].AnimalAI = AnimalAI.FleeWater;
Props[Block.fishsalmon].AnimalAI = AnimalAI.FleeWater;
Props[Block.fishsponge].AnimalAI = AnimalAI.FleeWater;
SetDefaultNames();
SetDefaultDeaths();

View File

@ -247,11 +247,11 @@ namespace MCGalaxy {
public static void SetBlocks() {
SetCoreProperties();
BlockBehaviour.InitCorePhysicsHandlers();
BlockProps.Load("core", Block.Props);
BlockBehaviour.InitCoreHandlers();
BlockPerms.Load();
BlockBehaviour.InitCorePhysicsHandlers();
BlockBehaviour.InitCoreHandlers();
}
[Obsolete("Use BlockPerms.CanModify()")]

View File

@ -21,6 +21,12 @@ using System.IO;
namespace MCGalaxy.Blocks {
/// <summary> Type of animal this block behaves as. </summary>
public enum AnimalAI : byte {
None, Fly, FleeAir, KillerAir, FleeWater, KillerWater, FleeLava, KillerLava,
}
/// <summary> Extended and physics properties of a block. </summary>
public struct BlockProps {
/// <summary> ID of block these properties are associated with. </summary>
@ -60,6 +66,9 @@ namespace MCGalaxy.Blocks {
/// <summary> Whether this block should allow trains to go over them. </summary>
public bool IsRails;
/// <summary> Animal AI behaviour of this block. </summary>
public AnimalAI AnimalAI;
/// <summary> Whether the properties for this block have been modified and hence require saving. </summary>
public bool Changed;
@ -79,7 +88,7 @@ namespace MCGalaxy.Blocks {
using (StreamWriter w = new StreamWriter("blockprops/" + group + ".txt")) {
w.WriteLine("# This represents the physics properties for blocks, in the format of:");
w.WriteLine("# id : Is rails : Is tdoor : Is door : Is message block : Is portal : " +
"Killed by water : Killed by lava : Kills players : death message");
"Killed by water : Killed by lava : Kills players : death message : Animal AI type");
for (int i = 0; i < scope.Length; i++) {
if (!scope[i].Changed) continue;
BlockProps props = scope[i];
@ -87,7 +96,8 @@ namespace MCGalaxy.Blocks {
string deathMsg = props.DeathMessage == null ? "" : props.DeathMessage.Replace(":", "\\;");
w.WriteLine(i + ":" + props.IsRails + ":" + props.IsTDoor + ":" + props.IsDoor + ":"
+ props.IsMessageBlock + ":" + props.IsPortal + ":" + props.WaterKills + ":"
+ props.LavaKills + ":" + props.KillerBlock + ":" + deathMsg);
+ props.LavaKills + ":" + props.KillerBlock + ":" + deathMsg + ":"
+ (byte)props.AnimalAI);
}
}
}
@ -125,6 +135,11 @@ namespace MCGalaxy.Blocks {
scope[id].DeathMessage = parts[9].Replace("\\;", ":");
if (scope[id].DeathMessage == "")
scope[id].DeathMessage = null;
if (parts.Length > 10) {
byte ai; byte.TryParse(parts[10], out ai);
scope[id].AnimalAI = (AnimalAI)ai;
}
}
}
}

View File

@ -121,7 +121,7 @@ namespace MCGalaxy.Blocks.Physics {
CheckAt(lvl, lvl.PosToInt(x, y, (ushort)(z + 1)));
CheckAt(lvl, lvl.PosToInt(x, y, (ushort)(z - 1)));
CheckAt(lvl, lvl.PosToInt(x, (ushort)(y + 1), z));
// ommision of y-1 to match original behaviour
// ommission of y-1 to match original behaviour
}
internal static void CheckAt(Level lvl, int index) {

View File

@ -120,11 +120,15 @@ namespace MCGalaxy.Commands.World {
} else if (prop == "deathmsg" || prop == "deathmessage") {
string msg = args.Length > 3 ? args[3] : null;
SetDeathMessage(p, scope, id, msg);
} else if (prop == "animalai" || prop == "animal") {
string msg = args.Length > 3 ? args[3] : null;
SetEnum(p, scope, id, msg);
} else {
Help(p);
}
}
delegate void BoolSetter(ref BlockProps props);
static void Toggle(Player p, BlockProps[] scope, byte id, string type,
BoolSetter setter, Func<BlockProps, bool> getter) {
@ -136,7 +140,18 @@ namespace MCGalaxy.Commands.World {
Player.Message(p, "Block {0} is {1}: {2}",
BlockName(scope, lvl, id),
type, getter(props) ? "&aYes" : "&cNo");
OnPropsChanged(scope, lvl, id);
OnPropsChanged(scope, lvl, id, false);
}
static void SetEnum(Player p, BlockProps[] scope, byte id, string msg) {
Level lvl = Player.IsSuper(p) ? null : p.level;
AnimalAI ai = AnimalAI.None;
if (!CommandParser.GetEnum(p, msg, "Animal AI", ref ai)) return;
scope[id].AnimalAI = ai;
Player.Message(p, "Animal AI for {0} set to: {1}",
BlockName(scope, lvl, id), ai);
OnPropsChanged(scope, lvl, id, true);
}
static void SetDeathMessage(Player p, BlockProps[] scope, byte id, string msg) {
@ -150,14 +165,16 @@ namespace MCGalaxy.Commands.World {
Player.Message(p, "Death message for {0} set to: {1}",
BlockName(scope, lvl, id), msg);
}
OnPropsChanged(scope, lvl, id);
OnPropsChanged(scope, lvl, id, false);
}
static void OnPropsChanged(BlockProps[] scope, Level level, byte id) {
static void OnPropsChanged(BlockProps[] scope, Level level, byte id, bool physics) {
scope[id].Changed = true;
if (scope == Block.Props) {
BlockBehaviour.InitCoreHandlers();
if (physics) BlockBehaviour.InitCorePhysicsHandlers();
BlockProps.Save("core", scope);
} else if (scope == BlockDefinition.GlobalProps) {
Level[] loaded = LevelInfo.Loaded.Items;
@ -190,7 +207,7 @@ namespace MCGalaxy.Commands.World {
Player.Message(p, "%H[scope] can be: %Score, global, level");
Player.Message(p, "%Hproperties: %Sportal, messageblock, rails, waterkills, " +
"lavakills, door, tdoor, killer, deathmessage");
"lavakills, door, tdoor, killer, deathmessage, animalai");
Player.Message(p, "%HType %T/help blockprops [property] %Hfor more details");
}
@ -214,6 +231,10 @@ namespace MCGalaxy.Commands.World {
} else if (message.CaselessEq("deathmessage")) {
Player.Message(p, "%HSets or removes the death message for this block");
Player.Message(p, "%H Note: %S@p %His a placeholder for the player's name");
} else if (message.CaselessEq("animalai")) {
Player.Message(p, "%HSets the flying or swimming animal AI for this block.");
string[] aiNames = Enum.GetNames(typeof(AnimalAI));
Player.Message(p, "%H Types: &f{0}", aiNames.Join());
} else {
Player.Message(p, "&cUnrecognised property \"{0}\"", message);
}