protected override IEnumerable <Toil> MakeNewToils() { this.FailOnDestroyedOrNull(InstrumentInd); Toil gotoThing = new Toil(); gotoThing.initAction = delegate { this.pawn.pather.StartPath(this.TargetThingA, PathEndMode.ClosestTouch); }; gotoThing.defaultCompleteMode = ToilCompleteMode.PatherArrival; gotoThing.FailOnDespawnedNullOrForbidden(InstrumentInd); yield return(gotoThing); Toil dropInstruments = new Toil(); dropInstruments.initAction = delegate { List <Thing> instruments = pawn.inventory.innerContainer.Where(x => PerformanceManager.IsInstrument(x)).ToList(); Thing result; foreach (Thing instrument in instruments) { pawn.inventory.innerContainer.TryDrop(instrument, pawn.Position, pawn.Map, ThingPlaceMode.Near, out result); } }; yield return(dropInstruments); yield return(Toils_Haul.TakeToInventory(InstrumentInd, 1)); }
public static void ApplyThoughts(Pawn listener, JoyKindDef joyKindDef) { if (joyKindDef != JoyKindDefOf_Music.Music) { return; } var thought = PerformanceManager.GetThoughtDef(MusicQuality); if (thought == null) { return; } var caravan = listener.GetCaravan(); var audience = new List <Pawn>(); foreach (var pawn in caravan.pawns) { if (!pawn.NonHumanlikeOrWildMan() && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Hearing) && pawn.Awake()) { audience.Add(pawn); } } #if DEBUG Verse.Log.Message(string.Format("Giving memory of {0} to {1} pawns (caravan)", thought.stages[0].label, audience.Count())); #endif foreach (var audienceMember in audience) { audienceMember.needs.mood.thoughts.memories.TryGainMemory(thought); } }
public bool TryFindStandingSpotOrChair(CompMusicSpot musicSpot, Pawn musician, Thing instrument, out LocalTargetInfo target) { IntVec3 standingSpot; Thing chair; target = null; PerformanceManager pm = musician.Map.GetComponent <PerformanceManager>(); CompMusicalInstrument comp = instrument.TryGetComp <CompMusicalInstrument>(); if (comp.Props.isBuilding) { if (pm.TryFindChairAt(comp, musician, out chair)) { target = chair; return(true); } else if (pm.TryFindSpotAt(comp, musician, out standingSpot)) { target = standingSpot; return(true); } } else { if (pm.TryFindSitSpotOnGroundNear(musicSpot, musician, out standingSpot)) { target = standingSpot; return(true); } } return(false); }
public override void PostDeSpawn(Map map) { base.PostDeSpawn(map); if (Active) { PerformanceManager pm = map.GetComponent <PerformanceManager>(); pm.RegisterDeactivatedMusicSpot(this); } }
static void Prefix(Map map, ref List <JoyKindDef> ___tempKindList) { PerformanceManager pm = map.GetComponent <PerformanceManager>(); Thing exampleInstrument; if (pm.MusicJoyKindAvailable(out exampleInstrument)) { ___tempKindList.Add(JoyKindDefOf_Music.Music); } }
public override void PostSpawnSetup(bool respawningAfterLoad) { base.PostSpawnSetup(respawningAfterLoad); if (parent.Faction != Faction.OfPlayer && !respawningAfterLoad) { active = false; } if (Active) { PerformanceManager pm = parent.Map.GetComponent <PerformanceManager>(); pm.RegisterActivatedMusicSpot(this); } }
static void Postfix(ref string __result, Map map) { PerformanceManager pm = map.GetComponent <PerformanceManager>(); string label = JoyKindDefOf_Music.Music.LabelCap; Thing exampleInstrument; //yuck if (!__result.Contains(label) && pm.MusicJoyKindAvailable(out exampleInstrument)) { __result += String.Format("\n {0} ({1})", label, exampleInstrument.def.label); } }
public override Job TryGiveJobWhileInBed(Pawn pawn) { #if DEBUG Verse.Log.Message("TryGiveJobWhileInBed " + pawn.Label); #endif Room room = pawn.GetRoom(); PerformanceManager pm = pawn.Map.GetComponent <PerformanceManager>(); // get music spots in pawn's current room List <CompMusicSpot> localMusicSpots = pm.ListActiveMusicSpots().Where(x => room.Cells.Contains(x.parent.Position)).ToList(); // if no music spots then give up if (localMusicSpots.Count == 0) { return(null); } #if DEBUG Verse.Log.Message(String.Format("{0} local spots", localMusicSpots.Count)); #endif workingSpots = localMusicSpots; // pick a random one CompMusicSpot CompMusicSpot; while (workingSpots.TryRandomElement(out CompMusicSpot)) { workingSpots.Remove(CompMusicSpot); // is a performance currently in progress if (pawn.Map.GetComponent <PerformanceManager>().HasPerformance(CompMusicSpot.parent)) { #if DEBUG Verse.Log.Message("Found performance"); #endif Job job = new Job(def.jobDef, CompMusicSpot.parent, pawn.CurrentBed()); return(job); } } return(null); }
static void Postfix(Pawn p, List <JoyKindDef> outJoyKinds, ref Caravan ___caravan) { if (!p.health.capacities.CapableOf(PawnCapacityDefOf.Hearing) || !p.Awake()) { return; } if (p.needs.joy.tolerances.BoredOf(JoyKindDefOf_Music.Music)) { return; } float quality; List <Pawn> pawnsTmp = new List <Pawn>(); pawnsTmp.AddRange(___caravan.pawns); Pawn musician; while (pawnsTmp.TryRandomElement(out musician)) { if (PerformanceManager.IsPotentialCaravanMusician(musician, out quality)) { outJoyKinds.Add(JoyKindDefOf_Music.Music); PatchTrySatisfyJoyNeed.MusicQuality = quality; #if DEBUG Verse.Log.Message(String.Format("Checking caravanner {0} for music availability : yes", p.Label)); #endif return; } else { pawnsTmp.Remove(musician); } } #if DEBUG Verse.Log.Message(String.Format("Checking caravanner {0} for music availability: no", p.Label)); #endif }
//public override ThingRequest PotentialWorkThingRequest => //Verse.Log.Message("PotentialWorkThingRequest"); //Unsatisfactory... need to narrow this down as I can't figure out how to get it to only use PotentialWorkThingsGlobal //ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial); public override IEnumerable <Thing> PotentialWorkThingsGlobal(Pawn pawn) { var pm = pawn.Map.GetComponent <PerformanceManager>(); if (!pm.CanPlayForWorkNow(pawn)) { return(null); } var things = pm.ListActiveMusicSpots().Select(x => (Thing)x.parent); //we also need to check for availibilty of an instrument here if (PerformanceManager.HeldInstrument(pawn) == null) { things = things.Where(x => pm.AnyAvailableMapInstruments(pawn, x)); } //Verse.Log.Message(String.Format("PotentialWorkThingsGlobal for {0}: {1} things", pawn.Label, things.Count())); return(things); }
private static bool Prefix(Pawn_InventoryTracker __instance, ref ThingCount __result) { if (__instance.innerContainer.Count == 0) { __result = default; return(false); } tmpDrugsToKeep.Clear(); if (__instance.pawn.drugs?.CurrentPolicy != null) { var currentPolicy = __instance.pawn.drugs.CurrentPolicy; for (var i = 0; i < currentPolicy.Count; i++) { if (currentPolicy[i].takeToInventory > 0) { tmpDrugsToKeep.Add(new ThingDefCount(currentPolicy[i].drug, currentPolicy[i].takeToInventory)); } } } Thing bestInstrument = null; if (!__instance.pawn.NonHumanlikeOrWildMan() && !__instance.pawn.WorkTagIsDisabled(WorkTags.Artistic)) { var artSkill = __instance.pawn.skills.GetSkill(SkillDefOf.Artistic).levelInt; IEnumerable <Thing> heldInstruments = __instance.innerContainer .Where(PerformanceManager.IsInstrument) .Where(x => !x.TryGetComp <CompMusicalInstrument>().Props.isBuilding) .OrderByDescending(x => x.TryGetComp <CompMusicalInstrument>().WeightedSuitability(artSkill)); if (heldInstruments.Any()) { bestInstrument = heldInstruments.FirstOrDefault(); } } if (tmpDrugsToKeep.Any() || bestInstrument != null) { foreach (var thing in __instance.innerContainer) { if (thing.def.IsDrug) { var num = -1; for (var k = 0; k < tmpDrugsToKeep.Count; k++) { if (thing.def != tmpDrugsToKeep[k].ThingDef) { continue; } num = k; break; } if (num < 0) { __result = new ThingCount(thing, thing.stackCount); return(false); } if (thing.stackCount > tmpDrugsToKeep[num].Count) { __result = new ThingCount(thing, thing.stackCount - tmpDrugsToKeep[num].Count); return(false); } tmpDrugsToKeep[num] = new ThingDefCount(tmpDrugsToKeep[num].ThingDef, tmpDrugsToKeep[num].Count - thing.stackCount); } else if (PerformanceManager.IsInstrument(thing)) { if (bestInstrument == null) { __result = new ThingCount(thing, thing.stackCount); return(false); } if (bestInstrument.GetHashCode() == thing.GetHashCode()) { continue; } __result = new ThingCount(thing, thing.stackCount); return(false); } else { __result = new ThingCount(thing, thing.stackCount); return(false); } } __result = default; return(false); } __result = new ThingCount(__instance.innerContainer[0], __instance.innerContainer[0].stackCount); return(false); }
// this function does three things: // it adds generic delegate functions to globalFailConditions (inherited from IJobEndable) via `This.EndOn...` extensions // it also yield returns a collection of toils: some generic, some custom // it also interacts with the JoyUtility static class so the pawns get joy protected override IEnumerable <Toil> MakeNewToils() { this.EndOnDespawnedOrNull(MusicSpotParentInd, JobCondition.Incompletable); //Verse.Log.Message(String.Format("Gather Spot ID = {0}", TargetA.Thing.GetHashCode())); Pawn musician = this.pawn; this.FailOnDestroyedNullOrForbidden(InstrumentInd); Thing instrument = this.TargetC.Thing; Thing venue = this.TargetA.Thing; CompProperties_MusicalInstrument props = instrument.TryGetComp <CompMusicalInstrument>().Props; if (props.isBuilding) { this.FailOn(() => PowerMissing(instrument)); // go to where instrument is yield return(Toils_Goto.GotoThing(InstrumentInd, PathEndMode.InteractionCell) .FailOnSomeonePhysicallyInteracting(InstrumentInd)); yield return(GetPlayToil(musician, instrument, venue)); } else { if (instrument.ParentHolder != musician.inventory) { // go to where instrument is yield return(Toils_Goto.GotoThing(InstrumentInd, PathEndMode.OnCell).FailOnSomeonePhysicallyInteracting(InstrumentInd)); //drop other instruments if any List <Thing> heldInstruments = pawn.inventory.innerContainer.Where(x => PerformanceManager.IsInstrument(x)).ToList(); if (heldInstruments.Any()) { Toil dropInstruments = new Toil(); dropInstruments.initAction = delegate { Thing result; foreach (Thing heldInstrument in heldInstruments) { pawn.inventory.innerContainer.TryDrop(heldInstrument, pawn.Position, pawn.Map, ThingPlaceMode.Near, out result); } }; yield return(dropInstruments); } // pick up instrument yield return(Toils_Haul.StartCarryThing(InstrumentInd)); } else { //get instrument out ready to play yield return(Toils_Misc.TakeItemFromInventoryToCarrier(musician, InstrumentInd)); } // go to the sitting / standing spot yield return(Toils_Goto.GotoCell(StandingSpotOrChairInd, PathEndMode.OnCell)); yield return(GetPlayToil(musician, instrument, venue)); //yield return Toils_General.PutCarriedThingInInventory(); } }
private Job TryGiveJobInt(Pawn pawn, Predicate <CompMusicSpot> musicSpotValidator) { #if DEBUG Verse.Log.Message(String.Format("{0} trying to listen to music", pawn.LabelShort)); #endif PerformanceManager pm = pawn.Map.GetComponent <PerformanceManager>(); // if no music spots then give up if (pm.ListActiveMusicSpots().Count == 0) { return(null); } // load all music spots on map into list workingSpots.Clear(); for (int i = 0; i < pm.ListActiveMusicSpots().Count; i++) { workingSpots.Add(pm.ListActiveMusicSpots()[i]); } // pick a random one CompMusicSpot CompMusicSpot; while (workingSpots.TryRandomElement(out CompMusicSpot)) { // remove from list workingSpots.Remove(CompMusicSpot); // check zones etc if (!CompMusicSpot.parent.IsForbidden(pawn)) { // see if there's a safe path to get there if (pawn.CanReach(CompMusicSpot.parent, PathEndMode.Touch, Danger.None, false, TraverseMode.ByPawn)) { // prisoners seperated from colonists if (CompMusicSpot.parent.IsSociallyProper(pawn)) { // only friendly factions if (CompMusicSpot.parent.IsPoliticallyProper(pawn)) { // check passed in predicate - i.e. parties if (musicSpotValidator == null || musicSpotValidator(CompMusicSpot)) { // is a performance currently in progress if (pawn.Map.GetComponent <PerformanceManager>().HasPerformance(CompMusicSpot.parent)) { #if DEBUG Verse.Log.Message("Found performance to listen to"); #endif // find a place to sit or stand, or return null if there aren't any Job job; IntVec3 standingSpot; if (pm.TryFindChairNear(CompMusicSpot, pawn, out Thing chair)) { #if DEBUG Verse.Log.Message("Found chair"); #endif job = new Job(this.def.jobDef, CompMusicSpot.parent, chair); return(job); } else if (pm.TryFindSitSpotOnGroundNear(CompMusicSpot, pawn, out standingSpot)) { #if DEBUG Verse.Log.Message("Found standing spot"); #endif job = new Job(this.def.jobDef, CompMusicSpot.parent, standingSpot); return(job); } else { #if DEBUG Verse.Log.Message("Failed to find chair or standing spot"); #endif return(null); } } } } } } } } #if DEBUG Verse.Log.Message("Failed to find performance"); #endif return(null); }
private Job TryGiveJobInt(Pawn pawn, Predicate <CompMusicSpot> musicSpotValidator) { //quit roll for low skill without instrument PerformanceManager pm = pawn.Map.GetComponent <PerformanceManager>(); int skill = pawn.skills.GetSkill(SkillDefOf.Artistic).Level; if (PerformanceManager.HeldInstrument(pawn) == null && skill < 3 && Verse.Rand.Chance(.75f)) { return(null); } // if no music spots then give up if (pm.ListActiveMusicSpots().Count == 0) { return(null); } if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Hearing) || !pawn.Awake() || pawn.WorkTagIsDisabled(WorkTags.Artistic)) { return(null); } // load all music spots on map into list JoyGiver_MusicPlay.workingSpots.Clear(); for (int i = 0; i < pm.ListActiveMusicSpots().Count; i++) { JoyGiver_MusicPlay.workingSpots.Add(pm.ListActiveMusicSpots()[i]); } // pick a random one CompMusicSpot CompMusicSpot; while (JoyGiver_MusicPlay.workingSpots.TryRandomElement(out CompMusicSpot)) { // remove from list JoyGiver_MusicPlay.workingSpots.Remove(CompMusicSpot); // check zones etc if (!CompMusicSpot.parent.IsForbidden(pawn)) { // see if there's a safe path to get there if (pawn.CanReach(CompMusicSpot.parent, PathEndMode.Touch, Danger.None, false, TraverseMode.ByPawn)) { // prisoners seperated from colonists if (CompMusicSpot.parent.IsSociallyProper(pawn)) { // only friendly factions if (CompMusicSpot.parent.IsPoliticallyProper(pawn)) { // check passed in predicate - i.e. parties if (musicSpotValidator == null || musicSpotValidator(CompMusicSpot)) { //check for an instrument if (PerformanceManager.HeldInstrument(pawn) != null || pm.AnyAvailableMapInstruments(pawn, CompMusicSpot.parent)) { Thing instrument; if (pm.TryFindInstrumentToPlay(CompMusicSpot.parent, pawn, out instrument)) { // find a place to sit or stand, or return null if there aren't any LocalTargetInfo chairOrSpot = null; if (pm.TryFindStandingSpotOrChair(CompMusicSpot, pawn, instrument, out chairOrSpot)) { Job job = new Job(def.jobDef, CompMusicSpot.parent, chairOrSpot, instrument); job.count = 1; return(job); } } } } } } } } } return(null); }
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Hearing) || !pawn.Awake() || pawn.WorkTagIsDisabled(WorkTags.Artistic)) { return(false); } PerformanceManager pm = pawn.Map.GetComponent <PerformanceManager>(); if (!pm.CanPlayForWorkNow(pawn)) { return(false); } CompMusicSpot compMusicSpot = t.TryGetComp <CompMusicSpot>(); CompMusicalInstrument instrumentComp = t.TryGetComp <CompMusicalInstrument>(); CompPowerTrader powerComp = t.TryGetComp <CompPowerTrader>(); if (compMusicSpot == null) { return(false); } if (!compMusicSpot.Active || instrumentComp == null) { return(false); } IntVec3 standingSpot; if (!pm.TryFindSitSpotOnGroundNear(compMusicSpot, pawn, out standingSpot)) { return(false); } Thing instrument; LocalTargetInfo chairOrSpot = null; if (forced && instrumentComp != null && instrumentComp.Props.isBuilding && pawn.CanReserveAndReach(t, PathEndMode.Touch, Danger.None) && (powerComp == null || powerComp.PowerOn)) { if (!pm.TryFindStandingSpotOrChair(compMusicSpot, pawn, t, out chairOrSpot)) { return(false); } } else if (pm.TryFindInstrumentToPlay(compMusicSpot.parent, pawn, out instrument, true)) { #if DEBUG Verse.Log.Message(String.Format("{0} chose to play {1}", pawn.LabelShort, instrument.LabelShort)); #endif if (!pm.TryFindStandingSpotOrChair(compMusicSpot, pawn, instrument, out chairOrSpot)) { return(false); } } else { return(false); } return(true); }
public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false) { //Verse.Log.Message(String.Format("Trying to play at {0}", thing.Label)); if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Hearing) || !pawn.Awake() || pawn.WorkTagIsDisabled(WorkTags.Artistic)) { return(null); } PerformanceManager pm = pawn.Map.GetComponent <PerformanceManager>(); if (!pm.CanPlayForWorkNow(pawn)) { return(null); } CompMusicSpot compMusicSpot = thing.TryGetComp <CompMusicSpot>(); if (compMusicSpot == null) { return(null); } if (!compMusicSpot.Active) { return(null); } Job job; IntVec3 standingSpot; if (!pm.TryFindSitSpotOnGroundNear(compMusicSpot, pawn, out standingSpot)) { return(null); } job = new Job(JobDefOf_MusicPlayWork.MusicPlayWork, compMusicSpot.parent); //, standingSpot); Thing instrument; CompMusicSpot musicSpotComp = thing.TryGetComp <CompMusicSpot>(); CompMusicalInstrument instrumentComp = thing.TryGetComp <CompMusicalInstrument>(); CompPowerTrader powerComp = thing.TryGetComp <CompPowerTrader>(); LocalTargetInfo chairOrSpot = null; if (forced && instrumentComp != null && instrumentComp.Props.isBuilding && pawn.CanReserveAndReach(thing, PathEndMode.Touch, Danger.None) && (powerComp == null || powerComp.PowerOn)) { if (!pm.TryFindStandingSpotOrChair(musicSpotComp, pawn, thing, out chairOrSpot)) { return(null); } job.targetB = chairOrSpot; job.targetC = thing; } else if (pm.TryFindInstrumentToPlay(compMusicSpot.parent, pawn, out instrument, true)) { #if DEBUG Verse.Log.Message(String.Format("{0} chose to play {1}", pawn.LabelShort, instrument.LabelShort)); #endif if (!pm.TryFindStandingSpotOrChair(musicSpotComp, pawn, instrument, out chairOrSpot)) { return(null); } job.targetB = chairOrSpot; job.targetC = instrument; } else { #if DEBUG Verse.Log.Message(String.Format("{0} couldn't find an instrument", pawn.LabelShort)); #endif return(null); } job.count = 1; return(job); }