private static void Add(bool isGoldenVersion) { string upperColor = isGoldenVersion ? "Golden" : "Black"; string lowerColor = isGoldenVersion ? "golden" : "black"; Gun gun = ETGMod.Databases.Items.NewGun($"{upperColor} Revolver", $"gr_{lowerColor}_revolver"); Game.Items.Rename($"outdated_gun_mods:{lowerColor}_revolver", $"ex:{lowerColor}_revolver"); gun.gameObject.AddComponent <BlackAndGoldenRevolver>(); gun.SetShortDescription("Six Deep"); string longDescription = "Bullets fired from this cursed revolver jam enemies on hit, but also completely ignore their increased strength, damaging them as if they were unjammed."; if (isGoldenVersion) { longDescription += "\n\nThree bullet kin, that were completely unalike each other, set aside their differences to obtain this revolver, that was once carried by the bearer of a terrible curse. Their presence can still be felt while wielding it."; } else { longDescription += "\n\nThis revolver was once carried by the bearer of a terrible curse. It is cold to the touch. A dark wind blows."; } gun.SetLongDescription(longDescription); // frame rate can be adjusted if we don't like the current idle animation speed gun.SetupSprite(null, $"gr_{lowerColor}_revolver_idle_001", 5); var idleAnimation = gun.GetComponent <tk2dSpriteAnimator>().GetClipByName(gun.idleAnimation); var list = idleAnimation.frames.ToList(); // manually add the reversal of the animation so we don't load the same sprite multiple times for no reason (these frames don't really need to be duplicated) list.Add(list[2]); list.Add(list[1]); // add a few more frames of the idle frame so the animation has a slight pause before looping for (int i = 0; i < 5; i++) { list.Add(list[0]); } idleAnimation.frames = list.ToArray(); gun.SetAnimationFPS(gun.shootAnimation, 12); gun.SetAnimationFPS(gun.reloadAnimation, 14); // Every modded gun has base projectile it works with that is borrowed from other guns in the game. // The gun names are the names from the JSON dump! While most are the same, some guns named completely different things. If you need help finding gun names, ask a modder on the Gungeon discord. // which means its the ETGMod.Databases.Items / PickupObjectDatabase.Instance.InternalGetByName name, aka the pickupobject.name var defaultGun = PickupObjectDatabase.GetById(22) as Gun; gun.AddProjectileModuleFrom(defaultGun, true, false); // move the gun up with the hand in the second frame of the shooting animation (hand movement was done in GAE with a y offset of 1) //gun.GetComponent<tk2dSpriteAnimator>().GetClipByName(gun.shootAnimation).frames[1].FrameToDefinition().MakeOffset(new Vector2(0, 1)); gun.gunSwitchGroup = defaultGun.gunSwitchGroup; gun.muzzleFlashEffects = defaultGun.muzzleFlashEffects; gun.AddMuzzle(); gun.muzzleOffset.localPosition = new Vector3(1.2f, 0.8f, 0f); gun.barrelOffset.localPosition = new Vector3(1.4f, 0.8f, 0f); gun.DefaultModule.shootStyle = ProjectileModule.ShootStyle.SemiAutomatic; gun.DefaultModule.sequenceStyle = ProjectileModule.ProjectileSequenceStyle.Random; gun.DefaultModule.cooldownTime = 0.07f; gun.DefaultModule.numberOfShotsInClip = 6; gun.DefaultModule.angleVariance = 0; gun.DefaultModule.ammoCost = 1; var curseWhileHeld = new StatModifier { amount = 2, statToBoost = PlayerStats.StatType.Curse, modifyType = StatModifier.ModifyMethod.ADDITIVE }; gun.currentGunStatModifiers = new StatModifier[] { curseWhileHeld }; gun.shellCasing = defaultGun.shellCasing; gun.shellsToLaunchOnFire = 0; gun.shellsToLaunchOnReload = gun.DefaultModule.numberOfShotsInClip; gun.reloadShellLaunchFrame = defaultGun.reloadShellLaunchFrame; gun.reloadTime = 1f; gun.gunClass = GunClass.PISTOL; gun.SetBaseMaxAmmo(666); gun.quality = PickupObject.ItemQuality.EXCLUDED; gun.encounterTrackable.EncounterGuid = $"this is the {lowerColor} skull revolver"; Projectile projectile = isGoldenVersion ? WestBrosGoldenRevolverProjectile.AddComponent <Projectile>() : WestBrosBlackRevolverProjectile.AddComponent <Projectile>(); GameObject projectileChild = projectile.transform.Find("Sprite").gameObject; tk2dSprite projetileSprite = SpriteSerializer.AddSpriteToObject(projectileChild, ExpandCustomEnemyDatabase.WestBrosCollection, "gr_black_revolver_projectile_001"); ExpandUtility.GenerateSpriteAnimator(projectileChild, playAutomatically: true); ExpandUtility.AddAnimation(projectileChild.GetComponent <tk2dSpriteAnimator>(), projetileSprite.Collection, ProjectileSpriteList, "idle", tk2dSpriteAnimationClip.WrapMode.Loop, 13); SpeculativeRigidbody projectileRigidBody = projectile.gameObject.AddComponent <SpeculativeRigidbody>(); ExpandUtility.DuplicateRigidBody(projectileRigidBody, defaultGun.DefaultModule.projectiles[0].specRigidbody); ExpandUtility.DuplicateComponent(projectile, defaultGun.DefaultModule.projectiles[0]); gun.DefaultModule.projectiles[0] = projectile; projectile.baseData.damage = 14f; projectile.baseData.speed = 25f; projectile.baseData.force = 14f; // projectile.transform.parent = gun.barrelOffset; projectile.transform.localPosition = gun.barrelOffset.localPosition; projectile.shouldRotate = true; var comp = projectile.gameObject.AddComponent <SkullRevolverBullet>(); comp.jamsEnemies = true; ETGMod.Databases.Items.Add(gun, null, "ANY"); if (isGoldenVersion) { AddHoveringGunComponent(gun); GoldenRevolverID = gun.PickupObjectId; } else { BlackRevolverID = gun.PickupObjectId; } }