internal void Update() // limited to 2s update since its low priority { if (OwnerCharacter != null && Time.time - lastUpdateTime > 2f) { lastUpdateTime = Time.time; if (Value != OwnerCharacter.Stats.ManaPoint * NecromancyBase.settings.Transcendence_DamageBonus) { Value = OwnerCharacter.Stats.ManaPoint * NecromancyBase.settings.Transcendence_DamageBonus; if (IsRegistered) { OwnerCharacter.Stats.RemoveStatStack(this.AffectedStat, this.SourceID, this.IsModifier); var m_statStack = OwnerCharacter.Stats.AddStatStack( this.AffectedStat, new StatStack( this.m_sourceID, this.Lifespan, this.Value * ((!this.IsModifier) ? 1f : 0.01f), null), this.IsModifier ); At.SetValue(m_statStack, typeof(AffectStat), this as AffectStat, "m_statStack"); } } } }
protected override void ActivateLocally(Character _affectedCharacter, object[] _infos) { if (SummonManager.Instance == null) { return; } if (SummonManager.Instance.FindWeakestSummon(_affectedCharacter.UID) is Character summonChar && summonChar.isActiveAndEnabled) { // change blast position to the summon's position _infos[0] = summonChar.transform.position; base.ActivateLocally(_affectedCharacter, _infos); // kill the summon summonChar.Stats.ReceiveDamage(999f); // fix for cooldown not working on this skill for some reason var skill = this.ParentItem as Skill; At.SetValue(Time.time, typeof(Skill), skill, "m_lastActivationTime"); At.SetValue(-1, typeof(Skill), skill, "m_lastCooldownProgress"); // plague aura interaction if (PlagueAuraProximityCondition.IsInsidePlagueAura(summonChar.transform.position)) { // if you're inside a plague aura, detonate resets your Summon cooldown. if (_affectedCharacter.Inventory.SkillKnowledge.GetItemFromItemID(8890103) is Skill summonSkill) { summonSkill.ResetCoolDown(); } } } }
public static void SetupFrenzy() { var frenzySkill = ResourcesPrefabManager.Instance.GetItemPrefab(8890105) as Skill; // setup skill frenzySkill.CastSheathRequired = -1; // destroy the existing skills, but keep the rest (VFX / Sound). DestroyImmediate(frenzySkill.transform.Find("Lightning").gameObject); DestroyImmediate(frenzySkill.transform.Find("SummonSoul").gameObject); // set custom spellcast anim At.SetValue(Character.SpellCastType.Focus, typeof(Item), frenzySkill as Item, "m_activateEffectAnimType"); var effects = new GameObject("Effects"); effects.transform.parent = frenzySkill.transform; effects.AddComponent <Frenzy>(); }
public void LocalTrainerSetup(Character trainer, string _) { // remove unwanted components DestroyImmediate(trainer.GetComponent <CharacterStats>()); DestroyImmediate(trainer.GetComponent <StartingEquipment>()); // add NPCLookFollow component trainer.gameObject.AddComponent <NPCLookFollow>(); // =========== setup Trainer DialogueTree from the template =========== var trainertemplate = Instantiate(Resources.Load("editor/templates/TrainerTemplate")) as GameObject; trainertemplate.transform.parent = trainer.transform; trainertemplate.transform.position = trainer.transform.position; // set Dialogue Actor name var necroActor = trainertemplate.GetComponentInChildren <DialogueActor>(); necroActor.SetName(trainerTemplate.Name); // get "Trainer" component, and set the SkillTreeUID to our custom tree UID Trainer trainerComp = trainertemplate.GetComponentInChildren <Trainer>(); At.SetValue(SkillManager.NecromancyTree.UID, typeof(Trainer), trainerComp, "m_skillTreeUID"); // setup dialogue tree var graphController = trainertemplate.GetComponentInChildren <DialogueTreeController>(); var graph = (graphController as GraphOwner <DialogueTreeExt>).graph; // the template comes with an empty ActorParameter, we can use that for our NPC actor. var actors = At.GetValue(typeof(DialogueTree), graph as DialogueTree, "_actorParameters") as List <DialogueTree.ActorParameter>; actors[0].actor = necroActor; actors[0].name = necroActor.name; // setup the actual dialogue now List <Node> nodes = At.GetValue(typeof(Graph), graph, "_nodes") as List <Node>; var rootStatement = graph.AddNode <StatementNodeExt>(); rootStatement.statement = new Statement("Do you seek to harness the power of Corruption, traveler?"); rootStatement.SetActorName(necroActor.name); var multiChoice1 = graph.AddNode <MultipleChoiceNodeExt>(); multiChoice1.availableChoices.Add(new MultipleChoiceNodeExt.Choice { statement = new Statement { text = "I'm interested, what can you teach me?" } }); multiChoice1.availableChoices.Add(new MultipleChoiceNodeExt.Choice { statement = new Statement { text = "Who are you?" } }); multiChoice1.availableChoices.Add(new MultipleChoiceNodeExt.Choice { statement = new Statement { text = "What is this place?" } }); // the template already has an action node for opening the Train menu. // Let's grab that and change the trainer to our custom Trainer component (setup above). var openTrainer = nodes[1] as ActionNode; (openTrainer.action as TrainDialogueAction).Trainer = new BBParameter <Trainer>(trainerComp); // create some custom dialogue var answer1 = graph.AddNode <StatementNodeExt>(); answer1.statement = new Statement("I wish I could remember..."); answer1.SetActorName(necroActor.name); var answer2 = graph.AddNode <StatementNodeExt>(); answer2.statement = new Statement("This is the fortress of the Plague Doctor, a powerful Lich. I've learned a lot about Corruption within these walls."); answer2.SetActorName(necroActor.name); // ===== finalize nodes ===== nodes.Clear(); // add the nodes we want to use nodes.Add(rootStatement); nodes.Add(multiChoice1); nodes.Add(openTrainer); nodes.Add(answer1); nodes.Add(answer2); graph.primeNode = rootStatement; graph.ConnectNodes(rootStatement, multiChoice1); // prime node triggers the multiple choice graph.ConnectNodes(multiChoice1, openTrainer, 0); // choice1: open trainer graph.ConnectNodes(multiChoice1, answer1, 1); // choice2: answer1 graph.ConnectNodes(answer1, rootStatement); // - choice2 goes back to root node graph.ConnectNodes(multiChoice1, answer2, 2); // choice3: answer2 graph.ConnectNodes(answer2, rootStatement); // - choice3 goes back to root node // set root node // set the trainer active trainer.gameObject.SetActive(true); }