rimworld-animations/1.4/Source/Comps/CompThingAnimator.cs
2022-10-05 13:50:02 -07:00

245 lines
6 KiB
C#

using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Verse;
namespace Rimworld_Animations {
public class CompThingAnimator : ThingComp
{
Vector3 anchor;
Pawn pawn;
public bool isAnimating = false, mirror;
int animTicks = 0, stageTicks = 0, clipTicks = 0, curStage = 0;
float rotation = 0;
float clipPercent = 0;
public Vector3 deltaPos;
AnimationDef anim;
private ThingAnimationClip clip => (ThingAnimationClip)stage.animationClips[1];
private AnimationStage stage
{
get
{
return anim.animationStages[curStage];
}
}
public void StartAnimation(AnimationDef anim, Pawn pawn, bool mirror = false)
{
isAnimating = true;
this.anim = anim;
this.pawn = pawn;
this.mirror = mirror;
animTicks = 0;
stageTicks = 0;
clipTicks = 0;
curStage = 0;
clipPercent = 0;
tickAnim();
}
public void setAnchor(IntVec3 position)
{
anchor = position.ToVector3();
}
public override void CompTick()
{
base.CompTick();
if(isAnimating)
{
if (pawn.Dead || pawn?.jobs?.curDriver == null || (pawn?.jobs?.curDriver != null && !(pawn?.jobs?.curDriver is rjw.JobDriver_Sex)))
{
isAnimating = false;
}
else
{
tickAnim();
}
}
}
public void tickAnim()
{
if (!isAnimating) return;
animTicks++;
if (animTicks < anim.animationTimeTicks)
{
tickStage();
}
else
{
if (LoopNeverending())
{
ResetOnLoop();
}
else
{
isAnimating = false;
}
}
}
public void tickStage()
{
if (stage == null)
{
isAnimating = false;
return;
}
stageTicks++;
if (stageTicks >= stage.playTimeTicks)
{
curStage++;
stageTicks = 0;
clipTicks = 0;
clipPercent = 0;
}
if (curStage >= anim.animationStages.Count)
{
if (LoopNeverending())
{
ResetOnLoop();
}
else
{
isAnimating = false;
}
}
else
{
tickClip();
}
}
public void tickClip()
{
clipTicks++;
if (clipPercent >= 1 && stage.isLooping)
{
clipTicks = 1;//warning: don't set to zero or else calculations go wrong
}
clipPercent = (float)clipTicks / (float)clip.duration;
calculateDrawValues();
}
public void setAnchor(Thing thing)
{
//center on bed
if (thing is Building_Bed)
{
anchor = thing.Position.ToVector3();
if (((Building_Bed)thing).SleepingSlotsCount == 2)
{
if (thing.Rotation.AsInt == 0)
{
anchor.x += 1;
anchor.z += 1;
}
else if (thing.Rotation.AsInt == 1)
{
anchor.x += 1;
}
else if (thing.Rotation.AsInt == 3)
{
anchor.z += 1;
}
}
else
{
if (thing.Rotation.AsInt == 0)
{
anchor.x += 0.5f;
anchor.z += 1f;
}
else if (thing.Rotation.AsInt == 1)
{
anchor.x += 1f;
anchor.z += 0.5f;
}
else if (thing.Rotation.AsInt == 2)
{
anchor.x += 0.5f;
}
else
{
anchor.z += 0.5f;
}
}
}
else
{
anchor = thing.Position.ToVector3Shifted();
}
anchor -= new Vector3(0.5f, 0, 0.5f);
}
private void calculateDrawValues()
{
//shift up and right 0.5f to align center
deltaPos = new Vector3((clip.PositionX.Evaluate(clipPercent)) * (mirror ? -1 : 1) + 0.5f, AltitudeLayer.Item.AltitudeFor(), clip.PositionZ.Evaluate(clipPercent) + 0.5f);
//Log.Message("Clip percent: " + clipPercent + " deltaPos: " + deltaPos);
rotation = clip.Rotation.Evaluate(clipPercent) * (mirror ? -1 : 1);
}
public void AnimateThing(Thing thing)
{
thing.Graphic.Draw(deltaPos + anchor, mirror ? Rot4.West : Rot4.East, thing, rotation);
}
public bool LoopNeverending()
{
if (pawn?.jobs?.curDriver != null &&
(pawn.jobs.curDriver is JobDriver_Sex) && (pawn.jobs.curDriver as JobDriver_Sex).neverendingsex)
{
return true;
}
return false;
}
public void ResetOnLoop()
{
curStage = 1;
animTicks = 0;
stageTicks = 0;
clipTicks = 0;
tickAnim();
}
}
}