Ryuushu

  • Content count

    111
  • Joined

  • Last visited

Community Reputation

43 Excellent

2 Followers

About Ryuushu

  • Rank
    Member
  1. Asymmetcrical Character Design?

    @MaiTerra I was poking around a bit more and figured out how to make idles work: --Remember to replace esctemplate with your character's prefab namelocal function ChangeAnim(inst) if inst.prefab ~= "esctemplate" or inst:HasTag("playerghost") then return end local dir = inst.Transform:GetRotation() local camera_rot = GLOBAL.TheCamera:GetHeadingTarget() % 360 print("Camera rotation:", camera_rot) print("Direction:", dir) if camera_rot == 0 or camera_rot == 45 then if dir <= -5 then inst.AnimState:SetBuild("esctemplate_right") else inst.AnimState:SetBuild("esctemplate_left") end elseif camera_rot == 90 or camera_rot == 135 then if math.abs(dir) >= 90 then inst.AnimState:SetBuild("esctemplate_right") else inst.AnimState:SetBuild("esctemplate_left") end elseif camera_rot == 180 or camera_rot == 225 then if dir >= -5 then inst.AnimState:SetBuild("esctemplate_right") else inst.AnimState:SetBuild("esctemplate_left") end else--if camera_rot == 270 or camera_rot == 315 then if math.abs(dir) <= 90 then inst.AnimState:SetBuild("esctemplate_right") else inst.AnimState:SetBuild("esctemplate_left") end endendlocal FRAMES = GLOBAL.FRAMESlocal TimeEvent = GLOBAL.TimeEventlocal function sg_postinit(sg) local old_locomote_event = sg.events.locomote.fn sg.events.locomote.fn = function(inst, data) ChangeAnim(inst) return old_locomote_event(inst, data) end if GLOBAL.TheWorld.ismastersim then local old_fishingcancel_event = sg.events.fishingcancel.fn sg.events.fishingcancel.fn = function(inst) ChangeAnim(inst) return old_fishingcancel_event(inst) end end -- Add/Remove TimeEvents as you see fitting. More TimeEvents = more accurate animations. Less TimeEvents = Slightly better performance. table.insert(sg.states["idle"].timeline, TimeEvent(20*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["idle"].timeline, TimeEvent(30*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["idle"].timeline, TimeEvent(40*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["idle"].timeline, TimeEvent(50*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["idle"].timeline, TimeEvent(60*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["idle"].timeline, TimeEvent(70*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["idle"].timeline, TimeEvent(80*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["idle"].timeline, TimeEvent(90*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["idle"].timeline, TimeEvent(100*FRAMES, function(inst) ChangeAnim(inst) end)) if GLOBAL.TheWorld.ismastersim then table.insert(sg.states["funnyidle"].timeline, TimeEvent(20*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["funnyidle"].timeline, TimeEvent(30*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["funnyidle"].timeline, TimeEvent(40*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["funnyidle"].timeline, TimeEvent(50*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["funnyidle"].timeline, TimeEvent(60*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["funnyidle"].timeline, TimeEvent(70*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["funnyidle"].timeline, TimeEvent(80*FRAMES, function(inst) ChangeAnim(inst) end)) end table.insert(sg.states["fishing"].timeline, TimeEvent(20*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["fishing"].timeline, TimeEvent(40*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["fishing"].timeline, TimeEvent(60*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["fishing"].timeline, TimeEvent(80*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["fishing"].timeline, TimeEvent(100*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["fishing"].timeline, TimeEvent(120*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["fishing"].timeline, TimeEvent(140*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["run_start"].timeline, TimeEvent(1*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["run"].timeline, TimeEvent(10*FRAMES, function(inst) ChangeAnim(inst) end)) table.insert(sg.states["run"].timeline, TimeEvent(20*FRAMES, function(inst) ChangeAnim(inst) end))endAddStategraphPostInit("wilson",sg_postinit)AddStategraphPostInit("wilson_client",sg_postinit) -- Haven't tested it in the client yet.It's more or less the same except this time it hooks into the stategraph. This time it changes the animation as it moves instead changing it only at the start (when the event is received). This also means it's a bit more intensive (still better than DoTaskInTime though). With this the idle animation + rotating camera should work. I'm still unsure about how well it works with clients. Haven't been able to test it myself. Also, this time it goes into modmain, put it anywhere inside it.
  2. Asymmetcrical Character Design?

    @MaiTerra It goes in the character's prefab file, inside master_postinit. Did you remember to load the anim assets? Hmm, posting the crash screen/error line helps too.
  3. Asymmetcrical Character Design?

    @MaiTerra After playing around for a while, it's quite possible, no need to remake all animations from scratch. And it's rather easy. Notice the eye color. Anyways, here's how you do it: First, save your current Spriter project as mycharacter_build_right. The side view will be the side that'll show when your character is facing right. Copy-paste your project folder (Spriter project + images) to a new folder. Then in that new Spriter project modify the side view images to your liking. Don't worry about your character facing right. Save your spriter project as mycharacter_build_left. Let the autocompiler do its job and throw your new anims in your mod anim folder. In your character file add the new anim assets. Now comes the fun part; handling which anim build we should use. We want to use mycharacter_build_right when it's facing right, and mycharacter_build_left when it's facing left. So, when do we know the character has started facing a side? We could use the event "locomote". That event will be sent when the character moves. So, we just add a listener to that event and use a bit of trickery to figure out what direction is the character facing: inst:ListenForEvent("locomote", function(inst) if inst:HasTag("playerghost") then return end local dir = inst.Transform:GetRotation() local camera_rot = TheCamera:GetHeadingTarget() print("Camera rotation:", camera_rot) print("Direction:", dir) if camera_rot < 0 then camera_rot = camera_rot + 360 end if camera_rot == 0 or camera_rot == 45 then if dir <= 0 then inst.AnimState:SetBuild("esctemplate_right") else inst.AnimState:SetBuild("esctemplate_left") end elseif camera_rot == 90 or camera_rot == 135 then if math.abs(dir) >= 90 then inst.AnimState:SetBuild("esctemplate_right") else inst.AnimState:SetBuild("esctemplate_left") end elseif camera_rot == 180 or camera_rot == 225 then if dir >= 0 then inst.AnimState:SetBuild("esctemplate_right") else inst.AnimState:SetBuild("esctemplate_left") end else--if camera_rot == 270 or camera_rot == 315 then if math.abs(dir) <= 90 then inst.AnimState:SetBuild("esctemplate_right") else inst.AnimState:SetBuild("esctemplate_left") end end end)endBasically what we do here is change our images depending on what side the character is facing. This should work relatively well. I haven't tested it with multiple players, but it should play along nicely. Also, there is another problem: The camera can keep rotating and go out of our scope. This should be solved by using the modulo operation ( % ) and then comparing. There might be some small problems with doing an action and then rotating the camera (like fishing), but nothing gamebreaking.