--------------------------- -- Simple AnimaL 1.00.00 -- --------------------------- -- i think there was this whole thing about turning globals into locals making Lua faster? local A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P = A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P -- driving frames local Q, R, S = Q, R, S -- attacked, squished, signpost local T, U, V, W, X, Y, Z = T, U, V, W, X, Y, Z -- mod frames. for frames after Z, -- use numbers (starting with 26.) local CURRENT_VERSION = 010000 local ANIMATION_DEFINITIONS = {} local SEQUENCE_HOOKS = {} -- This script is Reusable content by Togen. As part of its functions, it allows newer versions of the script to overwrite its functions. -- Review the all-caps variables above for configuration stuff that's relevant to you. Send me a message if you think somebody's got a -- weird hack that is doing bad things to other Simple AnimaLs, and I'll shoot them dead. -- Base sequences: -- drift -- drift_left -- drift_right -- goal -- pain -- run -- run_left -- run_right -- spin -- squish -- stand -- stand_left -- stand_right -- trick -- trick_left -- trick_right -- walk -- walk_left -- walk_right -- For anything else more complex, like checking if the player is airborne or underwater, create a sequence hook. All sequence hooks will -- be looped through, and the first result that returns a non-nil value will be used as the sequence value. Simple_AnimaL will handle the -- actual animation itself. local function this_Simple_AnimaL_thinker() local use_sequence = _G["SIMPLE_ANIMAL_CHANGER"] for mobj in thinkers.iterate("mobj") do if mobj.type == MT_PLAYER and _G["SIMPLE_ANIMAL_DEFINITIONS"][mobj.skin] then local running_threshold = mobj.scale * 20 local current_speed = mobj.player.speed local current_turning = mobj.player.cmd.driftturn local current_drift = mobj.player.kartstuff[k_drift] local current_grounded = P_IsObjectOnGround(mobj) if (mobj.player.kartstuff[k_squishedtimer] > 0) use_sequence(mobj, {"squish", "pain", "spin", "stand"}) elseif ((mobj.player.kartstuff[k_spinouttimer] > 0) or (mobj.player.powers[pw_nocontrol] and mobj.player.pflags & PF_SKIDDOWN) or mobj.player.pflags & PF_SLIDING) use_sequence(mobj, {"spin", "stand"}) elseif ((mobj.health <= 0) or (mobj.player.trickstun)) use_sequence(mobj, {"pain", "spin", "stand"}) elseif (mobj.player.trickactive or mobj.player.spintimer) and not(G_BattleGametype()) -- Acro. Basics doesn't use trick frames, but if (current_turning >= 0) -- this way is much cooler so it stays. use_sequence(mobj, {"trick_left", "trick", "drift_left", "drift", "walk_left", "walk", "stand_left", "stand"}) else use_sequence(mobj, {"trick_right", "trick", "drift_right", "drift", "walk_right", "walk", "stand_right", "stand"}) end elseif (mobj.player.speed == 0) if (current_turning < 0) use_sequence(mobj, {"stand_right", "stand"}) elseif (current_turning > 0) use_sequence(mobj, {"stand_left", "stand"}) elseif (current_turning == 0) use_sequence(mobj, {"stand"}) end elseif (current_drift > 0 and current_grounded) use_sequence(mobj, {"drift_left", "drift", "walk_left", "walk", "stand_left", "stand"}) elseif (current_drift < 0 and current_grounded) use_sequence(mobj, {"drift_right", "drift", "walk_right", "walk", "stand_right", "stand"}) elseif (current_speed > (running_threshold)) if (current_turning < 0) use_sequence(mobj, {"run_right", "run", "walk_right", "walk", "stand_right", "stand"}) elseif (current_turning > 0) use_sequence(mobj, {"run_left", "run", "walk_left", "walk", "stand_left", "stand"}) elseif (current_turning == 0) use_sequence(mobj, {"run", "walk", "stand"}) end elseif (current_speed <= (running_threshold)) if (current_turning < 0) use_sequence(mobj, {"walk_right", "walk", "stand_right", "stand"}) elseif (current_turning > 0) use_sequence(mobj, {"walk_left", "walk", "stand_left", "stand"}) elseif (current_turning == 0) use_sequence(mobj, {"walk", "stand"}) end end elseif mobj.type == MT_OVERLAY and mobj.state == S_PLAY_SIGN and _G["SIMPLE_ANIMAL_DEFINITIONS"][mobj.skin] then use_sequence(mobj, {"goal"}) end end end local function this_Simple_AnimaL_use_sequence(mobj, sequences) local skin = mobj.skin local last_sequence = mobj.Simple_AnimaL_sequence_last if not _G["SIMPLE_ANIMAL_DEFINITIONS"][skin] return end local validated_sequence for key, hook in pairs(_G["SIMPLE_ANIMAL_HOOKS"]) local result = hook(mobj, sequences) if result ~= nil validated_sequence = result break end end for key, sequence in pairs(sequences) if _G["SIMPLE_ANIMAL_DEFINITIONS"][skin][sequence] and validated_sequence == nil validated_sequence = sequence break end end local validated_sequence_table = _G["SIMPLE_ANIMAL_DEFINITIONS"][skin][validated_sequence] local validated_duration = #validated_sequence_table if (mobj.Simple_AnimaL_timer == nil) or (validated_sequence ~= last_sequence) mobj.Simple_AnimaL_timer = 1 mobj.Simple_AnimaL_sequence_last = validated_sequence elseif (validated_duration > 1) and (mobj.Simple_AnimaL_timer < validated_duration) mobj.Simple_AnimaL_timer = ($ + 1) else mobj.Simple_AnimaL_timer = 1 end local timer = max(1,mobj.Simple_AnimaL_timer) mobj.frame = validated_sequence_table[timer] end if not (_G["SIMPLE_ANIMAL_VERSION"]) then -- Step 1: Check if this is the first Simple AnimaL instance. rawset(_G, "SIMPLE_ANIMAL_VERSION", CURRENT_VERSION) rawset(_G, "SIMPLE_ANIMAL_THINKER", this_Simple_AnimaL_thinker) rawset(_G, "SIMPLE_ANIMAL_CHANGER", this_Simple_AnimaL_use_sequence) rawset(_G, "SIMPLE_ANIMAL_DEFINITIONS", {}) rawset(_G, "SIMPLE_ANIMAL_HOOKS", {}) addHook("PostThinkFrame", this_Simple_AnimaL_thinker) elseif (_G["SIMPLE_ANIMAL_VERSION"] < CURRENT_VERSION) then -- Step 2: Check if we can update other instances. rawset(_G, "SIMPLE_ANIMAL_VERSION", CURRENT_VERSION) rawset(_G, "SIMPLE_ANIMAL_THINKER", this_Simple_AnimaL_thinker) rawset(_G, "SIMPLE_ANIMAL_CHANGER", this_Simple_AnimaL_use_sequence) end -- Get defintions and hooks from this instance, add them to the global variables. for def, value in pairs(ANIMATION_DEFINITIONS) SIMPLE_ANIMAL_DEFINITIONS[def] = value end for key, hook in pairs(SEQUENCE_HOOKS) table.insert(SIMPLE_ANIMAL_HOOKS, hook) end