public override void SetupAttributes() { base.SetupAttributes(); rewindStateType = ContentAddition.AddEntityState <RewindState>(out _); R2API.Networking.NetworkingAPI.RegisterMessageType <MsgRewind>(); blacklistedSkills = new[] { LegacyResourcesAPI.Load <RoR2.Skills.SkillDef>("SkillDefs/CaptainBody/CallSupplyDropHealing"), LegacyResourcesAPI.Load <RoR2.Skills.SkillDef>("SkillDefs/CaptainBody/CallSupplyDropHacking"), LegacyResourcesAPI.Load <RoR2.Skills.SkillDef>("SkillDefs/CaptainBody/CallSupplyDropShocking"), LegacyResourcesAPI.Load <RoR2.Skills.SkillDef>("SkillDefs/CaptainBody/CallSupplyDropEquipmentRestock"), LegacyResourcesAPI.Load <RoR2.Skills.SkillDef>("SkillDefs/CaptainBody/CaptainSkillUsedUp"), LegacyResourcesAPI.Load <RoR2.Skills.SkillDef>("SkillDefs/CaptainBody/CaptainCancelDummy") }; rewindBuff = ScriptableObject.CreateInstance <BuffDef>(); rewindBuff.buffColor = Color.white; rewindBuff.canStack = true; rewindBuff.isDebuff = false; rewindBuff.isCooldown = true; rewindBuff.name = "TKSATRewind"; rewindBuff.iconSprite = TinkersSatchelPlugin.resources.LoadAsset <Sprite>("Assets/TinkersSatchel/Textures/MiscIcons/rewindBuffIcon.png"); ContentAddition.AddBuffDef(rewindBuff); if (Compat_ClassicItems.enabled) { LanguageAPI.Add("TKSAT_REWIND_CI_EMBRYO_APPEND", "\n<style=cStack>Beating Embryo: 50% chance to not consume stock.</style>"); Compat_ClassicItems.RegisterEmbryoHook(equipmentDef, "TKSAT_REWIND_CI_EMBRYO_APPEND", () => "TKSAT.CausalCamera"); } }
protected override bool PerformEquipmentAction(EquipmentSlot slot) { if (!slot || !slot.characterBody) { return(false); } var cpt = slot.characterBody.GetComponent <RewindComponent>(); if (!cpt || cpt.frames.Count == 0) { return(false); } var esm = EntityStateMachine.FindByCustomName(slot.characterBody.gameObject, "Body"); if (esm == null || esm.state is RewindState) { return(false); } new MsgRewind(slot.characterBody).Send(R2API.Networking.NetworkDestination.Clients); if (Compat_ClassicItems.enabled) { if (Util.CheckRoll(Mathf.Pow(0.5f, Compat_ClassicItems.CheckEmbryoProc(slot, equipmentDef)) * 100f)) { return(false); } } return(true); }
public override void SetupAttributes() { base.SetupAttributes(); var nSpriteD = TinkersSatchelPlugin.resources.LoadAsset <Sprite>("Assets/TinkersSatchel/Textures/packBoxArrowDown.png"); var nSpriteU = TinkersSatchelPlugin.resources.LoadAsset <Sprite>("Assets/TinkersSatchel/Textures/packBoxArrowUp.png"); var recy = LegacyResourcesAPI.Load <GameObject>("Prefabs/RecyclerIndicator").InstantiateClone("temporary setup prefab", false); foreach (var spr in recy.GetComponentsInChildren <SpriteRenderer>()) { if (spr.sprite.name != "texRecyclerArrow") { continue; } spr.sprite = nSpriteD; } placeIndicatorPrefab = recy.InstantiateClone("TkSatPackBoxPlaceIndicator", false); GameObject.Destroy(recy); recy = LegacyResourcesAPI.Load <GameObject>("Prefabs/RecyclerIndicator").InstantiateClone("temporary setup prefab", false); foreach (var spr in recy.GetComponentsInChildren <SpriteRenderer>()) { if (spr.sprite.name != "texRecyclerArrow") { continue; } spr.sprite = nSpriteU; } packIndicatorPrefab = recy.InstantiateClone("TkSatPackBoxPackIndicator", false); GameObject.Destroy(recy); recy = LegacyResourcesAPI.Load <GameObject>("Prefabs/RecyclerBadIndicator").InstantiateClone("temporary setup prefab", false); foreach (var spr in recy.GetComponentsInChildren <SpriteRenderer>()) { if (spr.sprite.name != "texRecyclerArrow") { continue; } spr.sprite = nSpriteD; } placeIndicatorBadPrefab = recy.InstantiateClone("TkSatPackBoxPlaceBadIndicator", false); GameObject.Destroy(recy); R2API.Networking.NetworkingAPI.RegisterMessageType <MsgPackboxPack>(); R2API.Networking.NetworkingAPI.RegisterMessageType <MsgPackboxPlace>(); if (Compat_ClassicItems.enabled) { LanguageAPI.Add("TKSAT_PACKBOX_CI_EMBRYO_APPEND", "\n<style=cStack>Beating Embryo: 50% chance to not consume stock on place.</style>"); Compat_ClassicItems.RegisterEmbryoHook(equipmentDef, "TKSAT_PACKBOX_CI_EMBRYO_APPEND", () => "TKSAT.CardboardBox"); } }
public override void SetupAttributes() { base.SetupAttributes(); droneMasterPrefabNames.UnionWith(masterNamesConfig.Split(',') .Select(x => x.Trim())); if (Compat_ClassicItems.enabled) { LanguageAPI.Add("TKSAT_REVIVEONCE_CI_EMBRYO_APPEND", "\n<style=cStack>Beating Embryo: Activates twice simultaneously.</style>"); Compat_ClassicItems.RegisterEmbryoHook(equipmentDef, "TKSAT_REVIVEONCE_CI_EMBRYO_APPEND", () => "TKSAT.CommandTerminal"); } }
protected override bool PerformEquipmentAction(EquipmentSlot slot) { var cpt = slot.characterBody.GetComponent <PackBoxTracker>(); if (!cpt) { cpt = slot.characterBody.gameObject.AddComponent <PackBoxTracker>(); } if (cpt.packedObject == null) { if (slot.currentTarget.rootObject && validObjectNames.Contains(slot.currentTarget.rootObject.name)) { var shopcpt = slot.currentTarget.rootObject.GetComponent <ShopTerminalBehavior>(); if (shopcpt && shopcpt.serverMultiShopController) { slot.currentTarget.rootObject = shopcpt.serverMultiShopController.transform.root.gameObject; } var pbh = slot.currentTarget.rootObject.GetComponent <PackBoxHandler>(); if (!pbh) { pbh = slot.currentTarget.rootObject.AddComponent <PackBoxHandler>(); } pbh.TryPackServer(cpt); return(false); } } else { var pbh = cpt.packedObject.GetComponent <PackBoxHandler>(); if (!pbh) { TinkersSatchelPlugin._logger.LogError("PackBoxTracker contains GameObject with no PackBoxHandler"); return(false); } if (TryGetBoxablePlacePos(slot.GetAimRay(), out Vector3 placeLoc, out _)) { var didPlace = pbh.TryPlaceServer(cpt, placeLoc); if (Compat_ClassicItems.enabled) { if (didPlace && Util.CheckRoll(Mathf.Pow(0.5f, Compat_ClassicItems.CheckEmbryoProc(slot, equipmentDef)) * 100f)) { return(false); } } return(didPlace); }
////// Hooks ////// protected override bool PerformEquipmentAction(EquipmentSlot slot) { var retv = PerformEquipmentActionInternal(slot); if (Compat_ClassicItems.enabled) { var count = Compat_ClassicItems.CheckEmbryoProc(slot, equipmentDef); for (var i = 0; i < count; i++) { retv |= PerformEquipmentActionInternal(slot); } } return(retv); }
void PullObjects(EquipmentSlot slot) { float range = objectRange; if (Compat_ClassicItems.enabled) { range *= 1f + (float)Compat_ClassicItems.CheckEmbryoProc(slot, equipmentDef); } var rbObjectsInRange = Physics.OverlapSphere(slot.characterBody.corePosition, range, Physics.AllLayers, QueryTriggerInteraction.Collide) .Select(x => x.gameObject) .Where(x => validObjectNamesRB.Contains(x.name)) .Select(x => x.GetComponent <Rigidbody>()) .Where(x => x); var nonRbObjectsInRange = GameObject.FindObjectsOfType <GameObject>() //TODO: add colliders to all of these prefabs .Where(x => validObjectNamesNoRB.Contains(x.name) && Vector3.Distance(x.transform.position, slot.characterBody.corePosition) < range); foreach (var rb in rbObjectsInRange) { var sticky = rb.gameObject.GetComponent <RoR2.Projectile.ProjectileStickOnImpact>(); if (sticky) { sticky.Detach(); sticky.enabled = false; } var velVec = slot.characterBody.transform.position - rb.transform.position; if (rb.useGravity && !rb.gameObject.name.Contains("TkSatPixie")) { var(vInitial, tFinal) = MiscUtil.CalculateVelocityForFinalPosition(rb.transform.position, slot.characterBody.transform.position, 1f); velVec = vInitial; } else { velVec.Normalize(); velVec *= PULL_FORCE; } rb.AddForce(velVec - rb.velocity, ForceMode.VelocityChange); } foreach (var nrb in nonRbObjectsInRange) { nrb.transform.position = slot.characterBody.corePosition; } }
void PullEnemies(EquipmentSlot slot) { float range = enemyRange; float damage = slot.characterBody.damage * baseDamageFrac; if (Compat_ClassicItems.enabled) { var fac = 1f + (float)Compat_ClassicItems.CheckEmbryoProc(slot, equipmentDef); range *= fac; damage *= fac; } var teamMembers = new List <TeamComponent>(); bool isFF = FriendlyFireManager.friendlyFireMode != FriendlyFireManager.FriendlyFireMode.Off; var scan = ((TeamIndex[])Enum.GetValues(typeof(TeamIndex))); var myTeam = TeamComponent.GetObjectTeam(slot.characterBody.gameObject); foreach (var ind in scan) { if (isFF || myTeam != ind) { teamMembers.AddRange(TeamComponent.GetTeamMembers(ind)); } } teamMembers.Remove(slot.characterBody.teamComponent); float sqrad = range * range; foreach (TeamComponent tcpt in teamMembers) { var velVec = slot.characterBody.transform.position - tcpt.transform.position; if (velVec.sqrMagnitude <= sqrad && tcpt.body && !tcpt.body.isBoss && !tcpt.body.isChampion && tcpt.body.isActiveAndEnabled) { var(vInitial, _) = MiscUtil.CalculateVelocityForFinalPosition(tcpt.transform.position, slot.characterBody.transform.position, 1f); var mcpt = tcpt.body.GetComponent <IPhysMotor>(); tcpt.body.healthComponent.TakeDamage(new DamageInfo { attacker = slot.characterBody.gameObject, crit = slot.characterBody.RollCrit(), damage = damage, damageColorIndex = DamageColorIndex.Default, damageType = DamageType.Generic | DamageType.AOE, canRejectForce = false, force = (vInitial - ((mcpt != null) ? mcpt.velocity : Vector3.zero)) * ((mcpt != null) ? mcpt.mass : 1f), position = tcpt.body.corePosition, procChainMask = default,
public override void SetupAttributes() { base.SetupAttributes(); var achiNameToken = $"ACHIEVEMENT_TKSAT_{name.ToUpper(System.Globalization.CultureInfo.InvariantCulture)}_NAME"; var achiDescToken = $"ACHIEVEMENT_TKSAT_{name.ToUpper(System.Globalization.CultureInfo.InvariantCulture)}_DESCRIPTION"; unlockable = ScriptableObject.CreateInstance <UnlockableDef>(); unlockable.cachedName = $"TkSat_{name}Unlockable"; unlockable.sortScore = 200; unlockable.achievementIcon = TinkersSatchelPlugin.resources.LoadAsset <Sprite>("Assets/TinkersSatchel/Textures/UnlockIcons/recombobulatorIcon.png"); ContentAddition.AddUnlockableDef(unlockable); LanguageAPI.Add(achiNameToken, "Risktaker"); LanguageAPI.Add(achiDescToken, "Recycle a rare or boss item."); equipmentDef.unlockableDef = unlockable; if (Compat_ClassicItems.enabled) { LanguageAPI.Add("TKSAT_RECOMBOBULATOR_CI_EMBRYO_APPEND", "\n<style=cStack>Beating Embryo: Roll twice and choose the rarer result.</style>"); Compat_ClassicItems.RegisterEmbryoHook(equipmentDef, "TKSAT_RECOMBOBULATOR_CI_EMBRYO_APPEND", () => "TKSAT.QuantumRecombobulator"); } }
public override void SetupAttributes() { base.SetupAttributes(); //load custom assets skillDef = TinkersSatchelPlugin.resources.LoadAsset <SkillDef>("Assets/TinkersSatchel/SkillDefs/CommandoSpecialPlasmaGrenade.asset"); scepterSkillDef = TinkersSatchelPlugin.resources.LoadAsset <SkillDef>("Assets/TinkersSatchel/SkillDefs/CIScepter/CommandoSpecialPlasmaGrenadeScep.asset"); projectilePrefab = TinkersSatchelPlugin.resources.LoadAsset <GameObject>("Assets/TinkersSatchel/Prefabs/Misc/CommandoPlasmaGrenadeProjectile.prefab"); var ghostPrefab = TinkersSatchelPlugin.resources.LoadAsset <GameObject>("Assets/TinkersSatchel/Prefabs/Misc/CommandoPlasmaGrenadeGhost.prefab"); scepterProjectilePrefab = TinkersSatchelPlugin.resources.LoadAsset <GameObject>("Assets/TinkersSatchel/Prefabs/Misc/CommandoPlasmaGrenadeProjectileScep.prefab"); var scepterGhostPrefab = TinkersSatchelPlugin.resources.LoadAsset <GameObject>("Assets/TinkersSatchel/Prefabs/Misc/CommandoPlasmaGrenadeGhostScep.prefab"); //load vanilla assets targetSkillFamily = Addressables.LoadAssetAsync <SkillFamily>("RoR2/Base/Commando/CommandoBodySpecialFamily.asset") .WaitForCompletion(); var detParticleMaterial = Addressables.LoadAssetAsync <Material>("RoR2/Base/Wisp/matWispFire.mat") .WaitForCompletion(); var fuseParticleMaterial = Addressables.LoadAssetAsync <Material>("RoR2/Base/ClayBoss/matClayBossLightshaft.mat") .WaitForCompletion(); var explosionPrefab = Addressables.LoadAssetAsync <GameObject>("RoR2/Base/LemurianBruiser/OmniExplosionVFXLemurianBruiserFireballImpact.prefab") .WaitForCompletion(); //modify var pRen = ghostPrefab.transform.Find("RadialGlow").gameObject.GetComponent <ParticleSystemRenderer>(); pRen.material = detParticleMaterial; var expl = projectilePrefab.GetComponent <ProjectileExplosion>(); expl.explosionEffect = explosionPrefab; var pRen2 = projectilePrefab.transform.Find("FuseVFX").gameObject.GetComponent <ParticleSystemRenderer>(); pRen2.material = fuseParticleMaterial; var scepterExplosionPrefabTmp = explosionPrefab.InstantiateClone("TkSatTempSetupPrefab", false); scepterExplosionPrefabTmp.transform.localScale *= 2f; var scepterExplosionPrefab = scepterExplosionPrefabTmp.InstantiateClone("TkSatPlasmaGrenadeScepterExplosion", false); pRen = scepterGhostPrefab.transform.Find("RadialGlow").gameObject.GetComponent <ParticleSystemRenderer>(); pRen.material = detParticleMaterial; expl = scepterProjectilePrefab.GetComponent <ProjectileExplosion>(); expl.explosionEffect = scepterExplosionPrefab; pRen2 = scepterProjectilePrefab.transform.Find("FuseVFX").gameObject.GetComponent <ParticleSystemRenderer>(); pRen2.material = fuseParticleMaterial; //R2API catalog reg var astate = ContentAddition.AddEntityState <Fire>(out bool entStateDidSucceed); skillDef.activationState = astate; scepterSkillDef.activationState = astate; if (!entStateDidSucceed) { TinkersSatchelPlugin._logger.LogError("EntityState setup failed on CommandoSpecialPlasmaGrenade! Skill will not appear nor function."); } else if (!ContentAddition.AddSkillDef(skillDef)) { TinkersSatchelPlugin._logger.LogError("SkillDef setup failed on CommandoSpecialPlasmaGrenade! Skill will not appear nor function."); } else { setupSucceeded = true; } ContentAddition.AddEffect(scepterExplosionPrefab); ContentAddition.AddProjectile(projectilePrefab); ContentAddition.AddProjectile(scepterProjectilePrefab); if (Compat_ClassicItems.enabled) { if (!ContentAddition.AddSkillDef(scepterSkillDef)) { scepSetupSucceeded = false; } else { scepSetupSucceeded = Compat_ClassicItems.RegisterScepterSkill(scepterSkillDef, "CommandoBody", SkillSlot.Special, skillDef); } if (!scepSetupSucceeded) { TinkersSatchelPlugin._logger.LogError("ClassicItems Scepter support failed for CommandoSpecialPlasmaGrenade! Ancient Scepter will not work on this skill."); } } }
public override void SetupAttributes() { base.SetupAttributes(); var tempPfb = LegacyResourcesAPI.Load <GameObject>("Prefabs/Projectiles/GravSphere").InstantiateClone("temporary setup prefab", false); var proj = tempPfb.GetComponent <RoR2.Projectile.ProjectileSimple>(); proj.desiredForwardSpeed = 0; proj.lifetime = 0.5f; var projCtrl = tempPfb.GetComponent <RoR2.Projectile.ProjectileController>(); projCtrl.procCoefficient = 0; var dmg = proj.GetComponent <RoR2.Projectile.ProjectileDamage>(); dmg.damage = 0f; dmg.enabled = false; var force = tempPfb.GetComponent <RadialForce>(); force.enabled = false; var sph = tempPfb.transform.Find("Sphere"); sph.gameObject.SetActive(false); var sps = tempPfb.transform.Find("Sparks"); var spsPart = sps.GetComponent <ParticleSystem>(); var spsShape = spsPart.shape; spsShape.radius = 30f; blackHolePrefab = tempPfb.InstantiateClone("LodestoneProcPrefab", true); UnityEngine.Object.Destroy(tempPfb); ContentAddition.AddProjectile(blackHolePrefab); validObjectNamesRB.UnionWith(new[] { "HealPack(Clone)", "StickyBomb(Clone)", "TkSatPixieMovePack(Clone)", "TkSatPixieAttackPack(Clone)", "TkSatPixieDamagePack(Clone)", "TkDatPixieArmorPack(Clone)", "AmmoPack(Clone)", "BonusMoneyPack(Clone)", "ShurikenProjectile(Clone)", "FireMeatBall(Clone)", "DeathProjectile(Clone)", "BeamSphere(Clone)", "GravSphere(Clone)", "Sawmerang(Clone)", "LunarSunProjectile(Clone)" }); validObjectNamesNoRB.UnionWith(new[] { //may have RB, but should teleport anyways "DeskplantWard(Clone)", "CrippleWard(Clone)", "WarbannerWard(Clone)", "DamageZoneWard(Clone)" }); var achiNameToken = $"ACHIEVEMENT_TKSAT_{name.ToUpper(System.Globalization.CultureInfo.InvariantCulture)}_NAME"; var achiDescToken = $"ACHIEVEMENT_TKSAT_{name.ToUpper(System.Globalization.CultureInfo.InvariantCulture)}_DESCRIPTION"; unlockable = ScriptableObject.CreateInstance <UnlockableDef>(); unlockable.cachedName = $"TkSat_{name}Unlockable"; unlockable.sortScore = 200; unlockable.achievementIcon = TinkersSatchelPlugin.resources.LoadAsset <Sprite>("Assets/TinkersSatchel/Textures/UnlockIcons/lodestoneIcon.png"); ContentAddition.AddUnlockableDef(unlockable); LanguageAPI.Add(achiNameToken, "Drive Me Closer"); LanguageAPI.Add(achiDescToken, "Item Set: Close-range. Have 6 or more (of 15) at once."); equipmentDef.unlockableDef = unlockable; if (Compat_ClassicItems.enabled) { LanguageAPI.Add("TKSAT_LODESTONE_CI_EMBRYO_APPEND", "\n<style=cStack>Beating Embryo: Double range and damage.</style>"); Compat_ClassicItems.RegisterEmbryoHook(equipmentDef, "TKSAT_LODESTONE_CI_EMBRYO_APPEND", () => "TKSAT.Lodestone"); } }
protected override bool PerformEquipmentAction(EquipmentSlot slot) { if (slot.currentTarget.rootObject && validObjectNames.Contains(slot.currentTarget.rootObject.name) && !slot.currentTarget.rootObject.GetComponent <RecombobulatorFlag>() && mostRecentDeck != null && Run.instance) { var oldPurch = slot.currentTarget.rootObject.GetComponent <PurchaseInteraction>(); if (oldPurch) { if (!oldPurch.available) { return(false); } } var shopcpt = slot.currentTarget.rootObject.GetComponent <ShopTerminalBehavior>(); if (shopcpt && shopcpt.serverMultiShopController) { slot.currentTarget.rootObject = shopcpt.serverMultiShopController.transform.root.gameObject; foreach (var term in shopcpt.serverMultiShopController.terminalGameObjects) { GameObject.Destroy(term); } } GameObject.Destroy(slot.currentTarget.rootObject); var pos = slot.currentTarget.rootObject.transform.position; WeightedSelection <DirectorCard> filteredDeck = new WeightedSelection <DirectorCard>(8); for (var i = 0; i < mostRecentDeck.Count; i++) { var card = mostRecentDeck.GetChoice(i); if (card.value != null && card.value.IsAvailable() && (validObjectNames.Contains(card.value.spawnCard.prefab.name) || validObjectNames.Contains(card.value.spawnCard.prefab.name + "(Clone)"))) { filteredDeck.AddChoice(card); } } if (filteredDeck.Count == 0) { return(false); } var draw = filteredDeck.Evaluate(rng.nextNormalizedFloat); if (Compat_ClassicItems.enabled) { var rerolls = Compat_ClassicItems.CheckEmbryoProc(slot, equipmentDef); for (var i = 0; i < rerolls; i++) { var draw2 = filteredDeck.Evaluate(rng.nextNormalizedFloat); if (draw2.selectionWeight < draw.selectionWeight) { draw = draw2; } } } var obj = DirectorCore.instance.TrySpawnObject( new DirectorSpawnRequest( draw.spawnCard, new DirectorPlacementRule { placementMode = DirectorPlacementRule.PlacementMode.Direct, position = pos, preventOverhead = false }, this.rng )); if (!obj) { TinkersSatchelPlugin._logger.LogError("Recombobulator failed to replace interactable!"); return(false); } var purch = obj.GetComponent <PurchaseInteraction>(); if (purch && purch.costType == CostTypeIndex.Money) { purch.Networkcost = Run.instance.GetDifficultyScaledCost(purch.cost); } obj.AddComponent <RecombobulatorFlag>(); var shopcpt2 = obj.GetComponent <MultiShopController>(); if (shopcpt2) { foreach (var term in shopcpt2.terminalGameObjects) { term.AddComponent <RecombobulatorFlag>(); } } return(true); } return(false); }