diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties
index d3547d049..c4aca1090 100644
--- a/core/src/main/assets/messages/items/items.properties
+++ b/core/src/main/assets/messages/items/items.properties
@@ -965,8 +965,13 @@ items.scrolls.exotic.exoticscroll.odal=exotic scroll of ODAL
items.scrolls.exotic.exoticscroll.tiwaz=exotic scroll of TIWAZ
items.scrolls.exotic.exoticscroll.unknown_desc=A glowing indecipherable magical rune is written on this black parchment. It seems to be foreign to this land, who knows what it will do when read aloud?
-items.scrolls.exotic.scrollofaffection.name=scroll of affection
-items.scrolls.exotic.scrollofaffection.desc=Reading this scroll will emit an alluring laugh which charms all who hear it.
+items.scrolls.exotic.scrollofsirenssong.name=scroll of siren's song
+items.scrolls.exotic.scrollofsirenssong.prompt=Choose a target
+items.scrolls.exotic.scrollofsirenssong.no_target=The scroll activates without a target
+items.scrolls.exotic.scrollofsirenssong.cancel=You must choose a target
+items.scrolls.exotic.scrollofsirenssong.desc=Reading this scroll emits an alluring melody which will enthrall a targeted enemy, permanently turning them into an ally! Other enemies who hear it will be temporarily charmed.\n\nParticularly strong enemies can resist the enthrall effect, and will be charmed instead.
+items.scrolls.exotic.scrollofsirenssong$enthralled.name=Enthralled
+items.scrolls.exotic.scrollofsirenssong$enthralled.desc=This creature has been bewitched by the magic of a scroll of siren's song.\n\nAn enthralled character is permanently your ally, and will fight any enemies they encounter.
items.scrolls.exotic.scrollofantimagic.name=scroll of anti-magic
items.scrolls.exotic.scrollofantimagic.desc=The incantation on this scroll will surround you with a magical aura that temporarily blocks all magical effects, harmful or helpful.
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ShatteredPixelDungeon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ShatteredPixelDungeon.java
index f13825f63..59d7fa517 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ShatteredPixelDungeon.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ShatteredPixelDungeon.java
@@ -45,9 +45,13 @@ public class ShatteredPixelDungeon extends Game {
public ShatteredPixelDungeon( PlatformSupport platform ) {
super( sceneClass == null ? WelcomeScene.class : sceneClass, platform );
+ //v1.1.0
com.watabou.utils.Bundle.addAlias(
com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfDread.class,
"com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPetrification" );
+ com.watabou.utils.Bundle.addAlias(
+ com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfSirensSong.class,
+ "com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfAffection" );
//v1.0.0
com.watabou.utils.Bundle.addAlias(
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ExoticScroll.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ExoticScroll.java
index 7a016e7f5..d11667ff9 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ExoticScroll.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ExoticScroll.java
@@ -57,8 +57,8 @@ public abstract class ExoticScroll extends Scroll {
regToExo.put(ScrollOfRemoveCurse.class, ScrollOfAntiMagic.class);
exoToReg.put(ScrollOfAntiMagic.class, ScrollOfRemoveCurse.class);
- regToExo.put(ScrollOfLullaby.class, ScrollOfAffection.class);
- exoToReg.put(ScrollOfAffection.class, ScrollOfLullaby.class);
+ regToExo.put(ScrollOfLullaby.class, ScrollOfSirensSong.class);
+ exoToReg.put(ScrollOfSirensSong.class, ScrollOfLullaby.class);
regToExo.put(ScrollOfRage.class, ScrollOfConfusion.class);
exoToReg.put(ScrollOfConfusion.class, ScrollOfRage.class);
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfAffection.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfAffection.java
deleted file mode 100644
index b1409ec43..000000000
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfAffection.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Pixel Dungeon
- * Copyright (C) 2012-2015 Oleg Dolya
- *
- * Shattered Pixel Dungeon
- * Copyright (C) 2014-2021 Evan Debenham
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
- */
-
-package com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic;
-
-import com.shatteredpixel.shatteredpixeldungeon.Assets;
-import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
-import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
-import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
-import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
-import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
-import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
-import com.watabou.noosa.audio.Sample;
-
-public class ScrollOfAffection extends ExoticScroll {
-
- {
- icon = ItemSpriteSheet.Icons.SCROLL_AFFECTION;
- }
-
- @Override
- public void doRead() {
-
- curUser.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
- Sample.INSTANCE.play( Assets.Sounds.CHARMS );
-
- for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
- if (Dungeon.level.heroFOV[mob.pos]) {
- Buff.affect( mob, Charm.class, Charm.DURATION*2f ).object = curUser.id();
- mob.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
- }
- }
-
- //GLog.i( Messages.get(this, "sooth") );
-
- identify();
-
- readAnimation();
-
- }
-
-}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfSirensSong.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfSirensSong.java
new file mode 100644
index 000000000..926d495bb
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/exotic/ScrollOfSirensSong.java
@@ -0,0 +1,146 @@
+/*
+ * Pixel Dungeon
+ * Copyright (C) 2012-2015 Oleg Dolya
+ *
+ * Shattered Pixel Dungeon
+ * Copyright (C) 2014-2021 Evan Debenham
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ */
+
+package com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic;
+
+import com.shatteredpixel.shatteredpixeldungeon.Assets;
+import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
+import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
+import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.AllyBuff;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm;
+import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
+import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
+import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.PotionOfDragonsBreath;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+import com.shatteredpixel.shatteredpixeldungeon.scenes.CellSelector;
+import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
+import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
+import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
+import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
+import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
+import com.watabou.noosa.audio.Sample;
+
+public class ScrollOfSirensSong extends ExoticScroll {
+
+ {
+ icon = ItemSpriteSheet.Icons.SCROLL_SIREN;
+ }
+
+ @Override
+ public void doRead() {
+ curItem.collect(); //we detach it later
+ GameScene.selectCell(targeter);
+ }
+
+ private CellSelector.Listener targeter = new CellSelector.Listener() {
+
+ @Override
+ public void onSelect(Integer cell) {
+ if (cell == null && isKnown() && !anonymous){
+ return;
+ }
+
+ Mob target = null;
+ if (cell != null){
+ Char ch = Actor.findChar(cell);
+ if (ch != null && ch.alignment != Char.Alignment.ALLY && ch instanceof Mob){
+ target = (Mob)ch;
+ }
+ }
+
+ if (target == null && isKnown() && !anonymous){
+ GLog.w(Messages.get(ScrollOfSirensSong.class, "cancel"));
+ return;
+
+ } else {
+
+ detach(curUser.belongings.backpack);
+
+ curUser.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
+ Sample.INSTANCE.play( Assets.Sounds.CHARMS );
+ Sample.INSTANCE.playDelayed( Assets.Sounds.LULLABY, 0.1f );
+
+ for (Mob mob : Dungeon.level.mobs.toArray( new Mob[0] )) {
+ if (Dungeon.level.heroFOV[mob.pos] && mob != target && mob.alignment != Char.Alignment.ALLY) {
+ Buff.affect( mob, Charm.class, Charm.DURATION ).object = curUser.id();
+ mob.sprite.centerEmitter().start( Speck.factory( Speck.HEART ), 0.2f, 5 );
+ }
+ }
+
+ if (target != null){
+ if (!target.isImmune(Enthralled.class)){
+ AllyBuff.affectAndLoot(target, curUser, Enthralled.class);
+
+ } else {
+ Buff.affect( target, Charm.class, Charm.DURATION ).object = curUser.id();
+
+ }
+ target.sprite.centerEmitter().burst( Speck.factory( Speck.HEART ), 10 );
+ } else {
+ GLog.w(Messages.get(ScrollOfSirensSong.class, "no_target"));
+ }
+
+ identify();
+
+ readAnimation();
+
+ }
+ }
+
+ @Override
+ public String prompt() {
+ return Messages.get(ScrollOfSirensSong.class, "prompt");
+ }
+
+ };
+
+ public static class Enthralled extends AllyBuff {
+
+ {
+ type = buffType.NEGATIVE;
+ announced = true;
+ }
+
+ @Override
+ public void fx(boolean on) {
+ if (on) target.sprite.add(CharSprite.State.HEARTS);
+ else target.sprite.remove(CharSprite.State.HEARTS);
+ }
+
+ @Override
+ public int icon() {
+ return BuffIndicator.HEART;
+ }
+
+ @Override
+ public String toString() {
+ return Messages.get(this, "name");
+ }
+
+ @Override
+ public String desc() {
+ return Messages.get(this, "desc");
+ }
+ }
+
+}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/CharSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/CharSprite.java
index 03da32af8..75bd208df 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/CharSprite.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/CharSprite.java
@@ -82,7 +82,7 @@ public class CharSprite extends MovieClip implements Tweener.Listener, MovieClip
protected float shadowOffset = 0.25f;
public enum State {
- BURNING, LEVITATING, INVISIBLE, PARALYSED, FROZEN, ILLUMINATED, CHILLED, DARKENED, MARKED, HEALING, SHIELDED
+ BURNING, LEVITATING, INVISIBLE, PARALYSED, FROZEN, ILLUMINATED, CHILLED, DARKENED, MARKED, HEALING, SHIELDED, HEARTS
}
private int stunStates = 0;
@@ -102,6 +102,7 @@ public class CharSprite extends MovieClip implements Tweener.Listener, MovieClip
protected Emitter marked;
protected Emitter levitation;
protected Emitter healing;
+ protected Emitter hearts;
protected IceBlock iceBlock;
protected DarkBlock darkBlock;
@@ -394,6 +395,10 @@ public class CharSprite extends MovieClip implements Tweener.Listener, MovieClip
case SHIELDED:
GameScene.effect( shield = new ShieldHalo( this ));
break;
+ case HEARTS:
+ hearts = emitter();
+ hearts.pour(Speck.factory(Speck.HEART), 0.5f);
+ break;
}
}
@@ -461,6 +466,12 @@ public class CharSprite extends MovieClip implements Tweener.Listener, MovieClip
shield.putOut();
}
break;
+ case HEARTS:
+ if (hearts != null){
+ hearts.on = false;
+ hearts = null;
+ }
+ break;
}
}
@@ -514,6 +525,12 @@ public class CharSprite extends MovieClip implements Tweener.Listener, MovieClip
if (marked != null) {
marked.visible = visible;
}
+ if (healing != null){
+ healing.visible = visible;
+ }
+ if (hearts != null){
+ hearts.visible = visible;
+ }
if (aura != null){
if (aura.parent == null){
aura.show(this, 0);
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java
index 2308ab993..e8969aa6a 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java
@@ -774,11 +774,11 @@ public class ItemSpriteSheet {
public static final int SCROLL_PRISIMG = EXOTIC_SCROLLS+3;
public static final int SCROLL_MYSTENRG = EXOTIC_SCROLLS+4;
public static final int SCROLL_PASSAGE = EXOTIC_SCROLLS+5;
- public static final int SCROLL_AFFECTION= EXOTIC_SCROLLS+6;
+ public static final int SCROLL_SIREN = EXOTIC_SCROLLS+6;
public static final int SCROLL_FORESIGHT= EXOTIC_SCROLLS+7;
public static final int SCROLL_CONFUSION= EXOTIC_SCROLLS+8;
public static final int SCROLL_PSIBLAST = EXOTIC_SCROLLS+9;
- public static final int SCROLL_DREAD = EXOTIC_SCROLLS+10;
+ public static final int SCROLL_DREAD = EXOTIC_SCROLLS+10;
public static final int SCROLL_POLYMORPH= EXOTIC_SCROLLS+11;
static {
assignIconRect( SCROLL_ENCHANT, 7, 7 );
@@ -787,7 +787,7 @@ public class ItemSpriteSheet {
assignIconRect( SCROLL_PRISIMG, 5, 7 );
assignIconRect( SCROLL_MYSTENRG, 7, 5 );
assignIconRect( SCROLL_PASSAGE, 5, 7 );
- assignIconRect( SCROLL_AFFECTION, 7, 6 );
+ assignIconRect( SCROLL_SIREN, 7, 6 );
assignIconRect( SCROLL_FORESIGHT, 7, 5 );
assignIconRect( SCROLL_CONFUSION, 7, 7 );
assignIconRect( SCROLL_PSIBLAST, 5, 6 );