From 24c4ae41852ff4199c717425a76e9df58db57af3 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Thu, 10 Sep 2020 17:20:46 -0400 Subject: [PATCH] v0.9.0: initial interface work for talents --- core/src/main/assets/effects/specks.png | Bin 501 -> 496 bytes .../main/assets/interfaces/talent_button.png | Bin 0 -> 4033 bytes .../main/assets/interfaces/talent_icons.png | Bin 0 -> 586 bytes .../assets/messages/actors/actors.properties | 4 +- .../src/main/assets/messages/ui/ui.properties | 3 + .../messages/windows/windows.properties | 4 + .../shatteredpixeldungeon/Assets.java | 4 +- .../actors/hero/Hero.java | 12 +- .../shatteredpixeldungeon/effects/Speck.java | 16 ++ .../scenes/GameScene.java | 7 + .../shatteredpixeldungeon/ui/StatusPane.java | 8 +- .../ui/TalentButton.java | 151 ++++++++++++++++++ .../shatteredpixeldungeon/ui/TalentsPane.java | 139 ++++++++++++++++ .../windows/WndGameInProgress.java | 2 +- .../windows/WndHero.java | 69 ++++++-- .../windows/WndInfoTalent.java | 91 +++++++++++ .../windows/WndRanking.java | 34 +++- .../windows/WndSettings.java | 2 +- 18 files changed, 519 insertions(+), 27 deletions(-) create mode 100644 core/src/main/assets/interfaces/talent_button.png create mode 100644 core/src/main/assets/interfaces/talent_icons.png create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentButton.java create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTalent.java diff --git a/core/src/main/assets/effects/specks.png b/core/src/main/assets/effects/specks.png index ce67c30ddc47cf34f8759d80846968fcdd5cea58..35492943f53d22379e72c8f1515e1090c0107094 100644 GIT binary patch delta 470 zcmV;{0V)3V1MmZoB!9O_L_t(|0qvK8Mg&n5hR<_^5Ks_JdWZlRy}__c02Z+G8UyG7 zA{IgfL=5x>iFtwm=x?v)<2p{=mazl-@tc{mSnK=exN9IY5!(?-YYVvSBw_)bDp`ik zqVHy2X7g|-Vvg0S5vl817V#ye@U>&W&n7|A(&ndJ0Le=%e}9H}u3kRLMQ_tO`7H$~ z$?snu2_-;0DHb4*t>{@*trUL`k~-q%&{%+8jzsn?-pBo*?zdu8`k}HA3J}XDr2-7Y zkRr=qMggJ{AiY?Epa6Z}=hAr=!hQPFTV?WlwQ6|gZI`qdlUREB@Av0~63kP8jUDr2 zvNBr=^R;5umVeXqO7Zf^_2!D`uL5*kmt^~-xfhT8asmA6e;$~Dg4llw(DH^;fDz;a zGYatebfR?C+r@qgkVL2C;)#uT`MYcYc z;c)?)aT6pK+*1I3+z<+|AN-pit$(R>K8Ts307$nCW>0wm{Jm{KxQ`WK?Q@Mwfc)Ya zATELCI|H~)K&JT@P~HHn{we+iu=4#ql;p<*hd_syU&0GNa9~!x0rG{Wyt*xEJpcdz M07*qoM6N<$f||$R-2eap delta 475 zcmV<10VMwL1N8%tB!9d~L_t(|0mPSqMg>6>hUYm#2q=hddWZm6y}?oh-~#Tx#sGSN zh=mXV5d*zJVxJ%cbn5KAAG5!;&2nw4&z||`a`F8$RWP$HAsCR&U^AAVM>81PkG2}- zC;Hu*Pt!i!8R*`6T^m$Y#r}ZsZRYfI2mhf@D8N_=kX}*(EkH`i2ViXoSJLsVW%83XR%dHY`}GdX@{0<9_@3uZuY6NHFDXDXJmHZU`8;G4 z;PdHdEB@_lnF6?ICl?Rd2UULY4S;+lFF?t!fLu6`X#v1<7p>xf?{M)z1}YyW zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1hxcI!G0{KqPK3E~KHIULV@89r>qE?muUoBq ztL;2X`ucIKQ$Hq=zv-G-Z`YHIy`a9t{<9M|Y-n=t=Coss< z@y_?-xEkom$mb_|wSM|wd|UPt?!}gI+Xx?SJ50DYzMA;5uzT#tK6mgi@5k9cbM`dn zSf?vK!lH3A>Y&p)G6oM;nB3{Gh!^80;4|wh-=g@2)doj9h*7cf6Sh*WKY7Hhc z81nH&-*x`xMRPVWkr892Wh?B<3UjdyK~8?-DF9;T#x1CU&)0_kxDX3e1%g4%oN&N$ z)HOv7=8IcSadvnv;C*?8A?|wum2^=cH1s_6)fkUE@Ly0c> z7-EbZMdS)Q_8d4ebK=Y;x#UwwF>y*Mr;=@U(7=#m=A3fQrC2Ihs9>&w=L=e@t*-hS zYOGvS&9yYpr}-9IY}``It#sR6hfMU?xu>3c8HNUwV)zk896Zv(v z&+djL1n4%z&8n28gpD076^A>`2CYE653EN49W^ zV6n*{*ibiu7$Ee+*f7llyD#K^gd2tQBi!ttkRyTa|A8C0Owtlo>9M%o zjEzf&HY3=^A}tnkf-YT`J)fhO2i^U|Iz9~#7V49*M#wP52=Z4pJZYBhdACDJq(|Ci zWDf&DIGBd~09OBGooZZTN5$*P*2CP##CChGqs;-s9dY(vYn(MThOK+7ZMf$0fY}Bt zT6Ju(z;zH03D%#%kxkfY5DA;_cc))K2R&0 z-B(e)XzF1ry0w#@eO>yBJ$Dz!Obq)6D8|4OB10g2u@$-u@yI5Xz^DKNa>xp29dOmz znlP}7z_g5^##?6pqhrab=;>IfolxA)Bu?_elOz3j|*! z4LBkijj7=Xns%I;hK<2eh(Sq6Tb;(IcSig1=sXEci_sc5*yNsD_EazWoqT;( zFZ!K)eO52}oqT;#uYv05LZXjMaaCdp5(&g1!D}MNR=zn&Gg@`Ml0+7V&{A-Cz?`B- zHZWQTe_X9PKdefEa%8>P{$)k zui=9HZGFAVb(B zmv1^^B%OBqgi1^Sb4?Wg-?(s|j*fE&NF7RnY0~ThJMxJgYO2#3vfL0cd^saEyX&y! zjoTMtNPd*3e{x54M!IDRI2fgVN&-+tp<^S;6VLhRn$(q}z3MrA0SPcro#`(2u13N} zoWfY5>nLoHP1XDC4Mh!njfZKP;-UT%lnPF<#2B><3TBpjOtn;8mXcB;<)`W>O5L+A z5u|6go4f|d729G9Y;$&$6*9F0&9%$M=(|;Zvk2X<;{0(eHf5pBOXe{z&1c#{r`iZg zS!3I@W)X1ckh4REm_C21pWnzo) zYp8}9-9y1U@=auV&~_B0l9`FJBg-TtH;`6jpn4mr&N-2S1}H+Y$N?d$SxS*v8=Sx? z=MG44k^~Z@KZFFBe_i`@j&b|EDAkbI0ZQmSo_lm>b#AEU=r_ z#0Uu3-b5W7kiJAzO$%3%G>r*-@aepCdheU_B3`X~;<_YnkL(Xy!R*o+`ohK1p`GrJ_9SG}DT;>o3av7h38)fqF6b|4vb zpQ8KO@p_?$8po#VSo)j6*Rk|BgZEe@;Gt5F@F4>tfTlCU?s}mq!o?N#h9vobY7T@! zsR=cQnnlsLssE{Mxd{{jE+R?^6@;gTZq6j_<&JS(4YYE6lgE+&^I*I4Y+27$V1J<7?25(5C?oS&)qfawi-SEALhokFN4*xH-@F3Syuju`()cU z)6#7Md}rMk8|JDxa*UEAVeQ$#5OcI8Xn2I#OiEWbqmWv3GE$79=@mKHkHxo#;MgIfK zy#Xw)xM=AB00D(*LqkwWLqi~Na&Km7Y-Iodc$|HaJxIeq9K~N-rL|NX+Cju2Lv^ws zDk4r&#UfZJZG~1HOfLO`CJjl7i=*ILaPVWX>fqw6tAnc`2!4P#IXWr2NQwVT3N2zh zIPS;0dyl(!fVWv?iqSI;D5|Na6LBGzUlshX=tBTu1TiZzLrZ2Bvv3_>_wexbF2=Lm z&;2?2<$}Qgk3c-fG~FcLAfDbdHO~9Q5mpvu;&b9Loi0fH$aTr#H_j!Sy*x9bXVde< z5n`d##ZniuvaS$M5l3Z3rF?JBVVUz5XQf(a?R)YUh6?IRhU+wkk-!p?NI`&vIx48b zM2uFI6a#76kGuGXY=4Se61gg1jFu>S-R0eZ?%w`A)9&vFjnHzkvl10m00006VoOIv z0RI600RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliruVV4Zp};3SQvpOv;>`5b^p_ z0}?TR^ZsSbI(UTx!13W}*R_7%ty(L!CTd*-niz3NN>hG8He2T&(^_${=gQ79A&h4PnQ1#dW4%hPU800000NkvXXu0mjfkHVKy literal 0 HcmV?d00001 diff --git a/core/src/main/assets/interfaces/talent_icons.png b/core/src/main/assets/interfaces/talent_icons.png new file mode 100644 index 0000000000000000000000000000000000000000..76201b99cd005d751d25337c0ea728382266902e GIT binary patch literal 586 zcmV-Q0=4~#P)m0|6!_Fi?Qe%*J3~z(8vNXt!)(69|GR?CVb8lgkRw z2>fOR6$r!-OeLhI3Q

IgJ<93tq7Gg6h`c9bR_c_F6Fsm5=nYFP9rRUv~ap)k>2( zUuT7&zhNr^Ku;Fa3=jZ-;DQ1?XE6Xo76JgIg%rav0eS$KR<#d56~LzeC;$UMWWE)t zQ2B4U{@ULH!1)#+^w-oESUxt*R#1W#VB9nt>I=-9=4DwqJbrFK0Qeh}Ky@D!!@2Rs z17I~Aj<^7Bx7+zT03g&z4hY5=&IDtq3Ipu}A5^YJb}$eY5dg4=@C5!B0Pl|~FjnzQ zrY*q0=Ou(6IuL!xJ4OHq9zT@_z-Yw)xY;?j0CzF#)kazg;uW#{002_bpN%v>fPBbk zBh3%Qy=F_tXd(eX03cONrx*_@n#cfnIG+_@{}$i%JK9L_15cO9hg9i=raL4X882{| zd@ip8biV{5God%3^#k-Vw0?lTh^!wVtYX43`mg8MB;*4`D|QKN)6tvIj2(Xr&EnxN zBC~q=tJoeN`Z2QS*Tzl*5K2I3LjD-?7g6_D@!#tFIWB&n_<`aFiXSL`p!k8}2Z|r~ Y0_KHCq0x7Lga7~l07*qoM6N<$f>l`YX#fBK literal 0 HcmV?d00001 diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index d66563fd0..682589f07 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -332,7 +332,9 @@ actors.hero.talent.test_huntress_4.desc=TODO actors.hero.hero.name=you actors.hero.hero.leave=You can't leave yet! actors.hero.hero.level_up=Level up! -actors.hero.hero.new_level=Level up!\nYou are more accurate, evasive, & healthy! +actors.hero.hero.new_level=Level up! +Accuracy, +Evasion, +5 HP! +actors.hero.hero.new_talent=+1 Talent Point! +actors.hero.hero.unspent=You have unspent talent points! actors.hero.hero.level_cap=You cannot grow stronger, but your experiences do give you a surge of power! actors.hero.hero.you_now_have=You picked up: %s. actors.hero.hero.you_cant_have=You can't carry: %s. diff --git a/core/src/main/assets/messages/ui/ui.properties b/core/src/main/assets/messages/ui/ui.properties index acca3a1d4..5585d1a62 100644 --- a/core/src/main/assets/messages/ui/ui.properties +++ b/core/src/main/assets/messages/ui/ui.properties @@ -1,5 +1,8 @@ ui.quickslotbutton.select_item=Quickslot an item +ui.talentspane.tier=tier %d +ui.talentspane.coming_soon=More talents coming soon! + ui.toolbar.examine_prompt=Press again to search\nPress a tile to examine ui.updatenotification.title=Update diff --git a/core/src/main/assets/messages/windows/windows.properties b/core/src/main/assets/messages/windows/windows.properties index d836ed679..35ef96907 100644 --- a/core/src/main/assets/messages/windows/windows.properties +++ b/core/src/main/assets/messages/windows/windows.properties @@ -37,6 +37,7 @@ windows.wndgameinprogress.erase_warn_yes=Yes, delete this save windows.wndgameinprogress.erase_warn_no=No, I want to continue windows.wndhero.stats=Stats +windows.wndhero.talents=Talents windows.wndhero.buffs=Buffs windows.wndhero$statstab.title=Level %1$d %2$s windows.wndhero$statstab.exp=Experience @@ -50,6 +51,8 @@ windows.wndimp.reward=Take the ring windows.wndinfocell.nothing=Nothing interesting here. +windows.wndinfotalent.upgrade=Upgrade Talent. + windows.wndinfotrap.inactive=This trap is inactive, and can no longer be triggered. windows.wndjournal.guide=Guide @@ -109,6 +112,7 @@ windows.wndranking.stats=Stats windows.wndranking.items=Items windows.wndranking.badges=Badges windows.wndranking$statstab.title=Level %1$d %2$s +windows.wndranking$statstab.talents=Talents windows.wndranking$statstab.challenges=Challenges windows.wndranking$statstab.health=Health windows.wndranking$statstab.str=Strength diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java index 63604f080..7780bed65 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Assets.java @@ -92,7 +92,9 @@ public class Assets { public static final String BUFFS_SMALL = "interfaces/buffs.png"; public static final String BUFFS_LARGE = "interfaces/large_buffs.png"; - public static final String CONS_ICONS = "interfaces/consumable_icons.png"; + + public static final String TALENT_ICONS = "interfaces/talent_icons.png"; + public static final String TALENT_BUTTON = "interfaces/talent_button.png"; } //these points to resource bundles, not raw asset files diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java index 84774b89c..4d177888a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java @@ -116,7 +116,9 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite; import com.shatteredpixel.shatteredpixeldungeon.ui.AttackIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton; +import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndHero; import com.shatteredpixel.shatteredpixeldungeon.windows.WndMessage; import com.shatteredpixel.shatteredpixeldungeon.windows.WndResurrect; import com.shatteredpixel.shatteredpixeldungeon.windows.WndTradeItem; @@ -306,6 +308,7 @@ public class Hero extends Char { } } + //TODO account for tiers public int talentPointsSpent(){ int total = 0; for (LinkedHashMap tier : talents){ @@ -316,6 +319,7 @@ public class Hero extends Char { return total; } + //TODO account for tiers public int talentPointsAvailable(){ //hero currently only gains points up to level 6 return Math.min(lvl, 6) - 1 - talentPointsSpent(); @@ -1431,9 +1435,15 @@ public class Hero extends Char { if (sprite != null) { GLog.newLine(); - GLog.p( Messages.get(this, "new_level"), lvl ); + GLog.p( Messages.get(this, "new_level") ); sprite.showStatus( CharSprite.POSITIVE, Messages.get(Hero.class, "level_up") ); Sample.INSTANCE.play( Assets.Sounds.LEVELUP ); + if (talentPointsAvailable() > 0){ + GLog.newLine(); + GLog.p( Messages.get(this, "new_talent") ); + StatusPane.talentBlink = 10f; + WndHero.lastIdx = 1; + } } Item.updateQuickslot(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Speck.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Speck.java index 9f22ecb53..4efa350b2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Speck.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/Speck.java @@ -89,6 +89,22 @@ public class Speck extends Image { origin.set( SIZE / 2f ); } + + public Speck image( int type ){ + reset(0, 0, 0, type); + + left = lifespan = Float.POSITIVE_INFINITY; + this.type = -1; + + resetColor(); + scale.set( 1 ); + speed.set( 0 ); + acc.set( 0 ); + angle = 0; + angularSpeed = 0; + + return this; + } public void reset( int index, float x, float y, int type ) { revive(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java index ec2ca0e7f..7dd9e03a6 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java @@ -469,6 +469,13 @@ public class GameScene extends PixelScene { GLog.h(Messages.get(this, "return"), Dungeon.depth); } + if (Dungeon.hero.talentPointsAvailable() > 0){ + GLog.newLine(); + GLog.w( Messages.get(Dungeon.hero, "unspent") ); + StatusPane.talentBlink = 10f; + WndHero.lastIdx = 1; + } + switch (Dungeon.level.feeling) { case CHASM: GLog.w(Messages.get(this, "chasm")); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/StatusPane.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/StatusPane.java index 824caa4fb..3f26d40c3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/StatusPane.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/StatusPane.java @@ -49,6 +49,7 @@ public class StatusPane extends Component { private NinePatch bg; private Image avatar; + public static float talentBlink; private float warning; private int lastTier = 0; @@ -104,6 +105,8 @@ public class StatusPane extends Component { avatar = HeroSprite.avatar( Dungeon.hero.heroClass, lastTier ); add( avatar ); + talentBlink = 0; + compass = new Compass( Statistics.amuletObtained ? Dungeon.level.entrance : Dungeon.level.exit ); add( compass ); @@ -124,7 +127,7 @@ public class StatusPane extends Component { add( bossHP ); level = new BitmapText( PixelScene.pixelFont); - level.hardlight( 0xFFEBA4 ); + level.hardlight( 0xFFFFAA ); add( level ); depth = new BitmapText( Integer.toString( Dungeon.depth ), PixelScene.pixelFont); @@ -200,6 +203,9 @@ public class StatusPane extends Component { warning += Game.elapsed * 5f *(0.4f - (health/max)); warning %= 1f; avatar.tint(ColorMath.interpolate(warning, warningColors), 0.5f ); + } else if (talentBlink > 0){ + talentBlink -= Game.elapsed; + avatar.tint(1, 1, 0, (float)Math.abs(Math.sin(2*talentBlink)/2f)); } else { avatar.resetColor(); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentButton.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentButton.java new file mode 100644 index 000000000..05e70d2a7 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentButton.java @@ -0,0 +1,151 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2020 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.ui; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; +import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; +import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; +import com.shatteredpixel.shatteredpixeldungeon.windows.WndInfoTalent; +import com.watabou.gltextures.SmartTexture; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; +import com.watabou.noosa.audio.Sample; +import com.watabou.noosa.particles.Emitter; +import com.watabou.noosa.ui.Button; +import com.watabou.utils.Callback; + +public class TalentButton extends Button { + + public static final int WIDTH = 20; + public static final int HEIGHT = 26; + + private SmartTexture icons; + private TextureFilm film; + + Talent talent; + boolean upgradeEnabled; + + Image icon; + Image bg; + + ColorBlock fill; + + public TalentButton(Talent talent, boolean upgradeEnabled){ + super(); + this.talent = talent; + this.upgradeEnabled = upgradeEnabled; + + icon.frame( film.get( talent.icon() ) ); + } + + @Override + protected void createChildren() { + super.createChildren(); + + icons = TextureCache.get( Assets.Interfaces.TALENT_ICONS ); + film = new TextureFilm( icons, 16, 16 ); + + fill = new ColorBlock(0, 4, 0xFFFFFF44); + add(fill); + + bg = new Image(Assets.Interfaces.TALENT_BUTTON, 20, 0, WIDTH, HEIGHT); + add(bg); + + icon = new Image( icons ); + add(icon); + } + + @Override + protected void layout() { + width = WIDTH; + height = HEIGHT; + + super.layout(); + + fill.x = x; + fill.y = y + WIDTH - 1; + fill.size( Dungeon.hero.pointsInTalent(talent)/2f * WIDTH, 5); + + bg.x = x; + bg.y = y; + + icon.x = x + 2; + icon.y = y + 2; + PixelScene.align(icon); + } + + @Override + protected void onClick() { + super.onClick(); + + if (upgradeEnabled + && Dungeon.hero != null + && Dungeon.hero.talentPointsAvailable() > 0 + && Dungeon.hero.pointsInTalent(talent) < talent.maxPoints()){ + ShatteredPixelDungeon.scene().addToFront(new WndInfoTalent(talent, new Callback() { + @Override + public void call() { + upgradeTalent(); + } + })); + } else { + ShatteredPixelDungeon.scene().addToFront(new WndInfoTalent(talent, null)); + } + } + + @Override + protected void onPointerDown() { + icon.brightness( 1.5f ); + bg.brightness( 1.5f ); + Sample.INSTANCE.play( Assets.Sounds.CLICK ); + } + + @Override + protected void onPointerUp() { + icon.resetColor(); + bg.resetColor(); + } + + public void enable( boolean value ) { + active = value; + icon.alpha( value ? 1.0f : 0.3f ); + bg.alpha( value ? 1.0f : 0.3f ); + } + + public void upgradeTalent(){ + if (Dungeon.hero.talentPointsAvailable() > 0) { + Dungeon.hero.upgradeTalent(talent); + float oldWidth = fill.width(); + layout(); + Sample.INSTANCE.play(Assets.Sounds.LEVELUP, 0.7f, 1.2f); + Emitter emitter = (Emitter) parent.recycle(Emitter.class); + emitter.revive(); + emitter.pos(fill.x + (fill.width() + oldWidth) / 2f, fill.y + fill.height() / 2f); + emitter.burst(Speck.factory(Speck.STAR), 12); + } + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java new file mode 100644 index 000000000..16192cf33 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/TalentsPane.java @@ -0,0 +1,139 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2020 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.ui; + +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; +import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; +import com.watabou.noosa.ColorBlock; +import com.watabou.noosa.Image; +import com.watabou.noosa.ui.Component; + +import java.util.ArrayList; + +//TODO some stuff here is currently coded without accounting for tiers +public class TalentsPane extends ScrollPane { + + RenderedTextBlock title; + ArrayList buttons; + + ArrayList stars; + + ColorBlock sep; + ColorBlock blocker; + RenderedTextBlock blockText; + + public TalentsPane( boolean canUpgrade ) { + super(new Component()); + + title = PixelScene.renderTextBlock(Messages.titleCase(Messages.get(this, "tier", 1)), 9); + title.hardlight(Window.TITLE_COLOR); + content.add(title); + + setupStars(); + + buttons = new ArrayList<>(); + for (Talent talent : Dungeon.hero.talents.get(0).keySet()){ + TalentButton btn = new TalentButton(talent, canUpgrade){ + @Override + public void upgradeTalent() { + super.upgradeTalent(); + setupStars(); + TalentsPane.this.layout(); + } + }; + buttons.add(btn); + content.add(btn); + } + + sep = new ColorBlock(0, 1, 0xFF000000); + content.add(sep); + + blocker = new ColorBlock(0, 0, 0xFF222222); + content.add(blocker); + + blockText = PixelScene.renderTextBlock(Messages.get(this, "coming_soon"), 6); + content.add(blockText); + } + + private void setupStars(){ + if (stars != null){ + for (Image im : stars){ + im.killAndErase(); + } + stars.clear(); + } else { + stars = new ArrayList<>(); + } + + int totStars = 5; + int openStars = Dungeon.hero.talentPointsAvailable(); + int usedStars = Dungeon.hero.talentPointsSpent(); + for (int i = 0; i < totStars; i++){ + Image im = new Speck().image(Speck.STAR); + stars.add(im); + add(im); + if (i >= openStars && i < (openStars + usedStars)){ + im.tint(0.75f, 0.75f, 0.75f, 0.9f); + } else if (i >= (openStars + usedStars)){ + im.tint(0f, 0f, 0f, 0.9f); + } + } + } + + @Override + protected void layout() { + super.layout(); + + float titleWidth = title.width(); + titleWidth += 2 + stars.size()*6; + title.setPos(x + (width - titleWidth)/2f, y+2); + + float left = title.right() + 2; + for (Image star : stars){ + star.x = left; + star.y = title.top(); + PixelScene.align(star); + left += 6; + } + + float gap = (width - buttons.size()*TalentButton.WIDTH)/(buttons.size()+1); + left = x + gap; + for (TalentButton btn : buttons){ + btn.setPos(left, title.bottom() + 4); + PixelScene.align(btn); + left += btn.width() + gap; + } + + sep.x = x; + sep.y = buttons.get(0).bottom() + 2; + sep.size(width, 1); + + blocker.x = x; + blocker.y = sep.y + 1; + blocker.size(width, height - sep.y - 1); + + blockText.setPos(x + (width - blockText.width())/2f, blocker.y + 10); + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndGameInProgress.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndGameInProgress.java index e5586a045..5047f170d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndGameInProgress.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndGameInProgress.java @@ -66,7 +66,7 @@ public class WndGameInProgress extends Window { IconTitle title = new IconTitle(); title.icon( HeroSprite.avatar(info.heroClass, info.armorTier) ); title.label((Messages.get(this, "title", info.level, className)).toUpperCase(Locale.ENGLISH)); - title.color(Window.SHPX_COLOR); + title.color(Window.TITLE_COLOR); title.setRect( 0, 0, WIDTH, 0 ); add(title); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java index 42d322c24..7588b4b35 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHero.java @@ -33,6 +33,8 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock; import com.shatteredpixel.shatteredpixeldungeon.ui.ScrollPane; +import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane; +import com.shatteredpixel.shatteredpixeldungeon.ui.TalentsPane; import com.shatteredpixel.shatteredpixeldungeon.ui.Window; import com.watabou.gltextures.SmartTexture; import com.watabou.gltextures.TextureCache; @@ -46,27 +48,28 @@ import java.util.Locale; public class WndHero extends WndTabbed { - private static final int WIDTH = 115; + private static final int WIDTH = 120; private static final int HEIGHT = 100; private StatsTab stats; + private TalentsTab talents; private BuffsTab buffs; - - private SmartTexture icons; - private TextureFilm film; - + + public static int lastIdx = 0; + public WndHero() { super(); resize( WIDTH, HEIGHT ); - icons = TextureCache.get( Assets.Interfaces.BUFFS_LARGE ); - film = new TextureFilm( icons, 16, 16 ); - stats = new StatsTab(); add( stats ); - + + talents = new TalentsTab(); + add(talents); + talents.setRect(0, 0, WIDTH, HEIGHT); + buffs = new BuffsTab(); add( buffs ); buffs.setRect(0, 0, WIDTH, HEIGHT); @@ -75,21 +78,31 @@ public class WndHero extends WndTabbed { add( new LabeledTab( Messages.get(this, "stats") ) { protected void select( boolean value ) { super.select( value ); + if (selected) lastIdx = 0; stats.visible = stats.active = selected; } } ); + add( new LabeledTab( Messages.get(this, "talents") ) { + protected void select( boolean value ) { + super.select( value ); + if (selected) lastIdx = 1; + if (selected) StatusPane.talentBlink = 0; + talents.visible = talents.active = selected; + } + } ); add( new LabeledTab( Messages.get(this, "buffs") ) { protected void select( boolean value ) { super.select( value ); + if (selected) lastIdx = 2; buffs.visible = buffs.active = selected; } } ); layoutTabs(); - select( 0 ); + select( lastIdx ); } - + private class StatsTab extends Group { private static final int GAP = 6; @@ -106,7 +119,7 @@ public class WndHero extends WndTabbed { title.label( Messages.get(this, "title", hero.lvl, hero.className() ).toUpperCase( Locale.ENGLISH ) ); else title.label((hero.name() + "\n" + Messages.get(this, "title", hero.lvl, hero.className())).toUpperCase(Locale.ENGLISH)); - title.color(Window.SHPX_COLOR); + title.color(Window.TITLE_COLOR); title.setRect( 0, 0, WIDTH, 0 ); add(title); @@ -147,16 +160,44 @@ public class WndHero extends WndTabbed { return pos; } } + + public class TalentsTab extends Component { + + TalentsPane pane; + + @Override + protected void createChildren() { + super.createChildren(); + pane = new TalentsPane(true); + add(pane); + } + + @Override + protected void layout() { + super.layout(); + pane.setRect(x, y, width, height); + } + + } private class BuffsTab extends Component { private static final int GAP = 2; + + private SmartTexture icons; + private TextureFilm film; private float pos; private ScrollPane buffList; private ArrayList slots = new ArrayList<>(); - - public BuffsTab() { + + @Override + protected void createChildren() { + icons = TextureCache.get( Assets.Interfaces.BUFFS_LARGE ); + film = new TextureFilm( icons, 16, 16 ); + + super.createChildren(); + buffList = new ScrollPane( new Component() ){ @Override public void onClick( float x, float y ) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTalent.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTalent.java new file mode 100644 index 000000000..893019a07 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTalent.java @@ -0,0 +1,91 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2020 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.windows; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; +import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton; +import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock; +import com.shatteredpixel.shatteredpixeldungeon.ui.Window; +import com.watabou.gltextures.SmartTexture; +import com.watabou.gltextures.TextureCache; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; +import com.watabou.utils.Callback; + +public class WndInfoTalent extends Window { + + private static final float GAP = 2; + + private static final int WIDTH = 120; + + private SmartTexture icons; + private TextureFilm film; + + public WndInfoTalent(Talent talent, Callback onUpgradeButton){ + super(); + + IconTitle titlebar = new IconTitle(); + + icons = TextureCache.get( Assets.Interfaces.TALENT_ICONS ); + film = new TextureFilm( icons, 16, 16 ); + + Image buffIcon = new Image( icons ); + buffIcon.frame( film.get(talent.icon()) ); + + titlebar.icon( buffIcon ); + String title = Messages.titleCase(talent.title()); + if (Dungeon.hero != null && Dungeon.hero.pointsInTalent(talent) > 0){ + title += " +" + Dungeon.hero.pointsInTalent(talent); + } + titlebar.label( title, Window.TITLE_COLOR ); + titlebar.setRect( 0, 0, WIDTH, 0 ); + add( titlebar ); + + RenderedTextBlock txtInfo = PixelScene.renderTextBlock(talent.desc(), 6); + txtInfo.maxWidth(WIDTH); + txtInfo.setPos(titlebar.left(), titlebar.bottom() + 2*GAP); + add( txtInfo ); + + resize( WIDTH, (int)(txtInfo.bottom() + GAP) ); + + if (onUpgradeButton != null) { + RedButton upgrade = new RedButton( Messages.get(this, "upgrade") ) { + @Override + protected void onClick() { + super.onClick(); + hide(); + onUpgradeButton.call(); + } + }; + upgrade.setRect(0, txtInfo.bottom() + 2*GAP, WIDTH, 16); + add(upgrade); + resize( WIDTH, (int)upgrade.bottom()+1 ); + } + + + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndRanking.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndRanking.java index cb15a30ac..e31282f24 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndRanking.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndRanking.java @@ -37,6 +37,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.ItemSlot; import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton; import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock; import com.shatteredpixel.shatteredpixeldungeon.ui.ScrollPane; +import com.shatteredpixel.shatteredpixeldungeon.ui.TalentsPane; import com.shatteredpixel.shatteredpixeldungeon.ui.Window; import com.watabou.noosa.ColorBlock; import com.watabou.noosa.Game; @@ -155,24 +156,40 @@ public class WndRanking extends WndTabbed { private class StatsTab extends Group { - private int GAP = 5; + private int GAP = 4; public StatsTab() { super(); - - if (Dungeon.challenges > 0) GAP--; String heroClass = Dungeon.hero.className(); IconTitle title = new IconTitle(); title.icon( HeroSprite.avatar( Dungeon.hero.heroClass, Dungeon.hero.tier() ) ); title.label( Messages.get(this, "title", Dungeon.hero.lvl, heroClass ).toUpperCase( Locale.ENGLISH ) ); - title.color(Window.SHPX_COLOR); + title.color(Window.TITLE_COLOR); title.setRect( 0, 0, WIDTH, 0 ); add( title ); float pos = title.bottom() + GAP; + RedButton btnTalents = new RedButton( Messages.get(this, "talents") ){ + @Override + protected void onClick() { + Game.scene().addToFront( new Window(){ + { + resize(120, 144); + TalentsPane p = new TalentsPane(false); + add(p); + p.setRect(0, 0, width, height); + } + }); + } + }; + btnTalents.setRect( (WIDTH - btnTalents.reqWidth()+2)/2, pos, btnTalents.reqWidth()+2 , 16 ); + add(btnTalents); + + pos = btnTalents.bottom(); + if (Dungeon.challenges > 0) { RedButton btnChallenges = new RedButton( Messages.get(this, "challenges") ) { @Override @@ -180,11 +197,14 @@ public class WndRanking extends WndTabbed { Game.scene().add( new WndChallenges( Dungeon.challenges, false ) ); } }; - float btnW = btnChallenges.reqWidth() + 2; - btnChallenges.setRect( (WIDTH - btnW)/2, pos, btnW , btnChallenges.reqHeight() + 2 ); + + btnChallenges.setSize( btnChallenges.reqWidth()+2, 16 ); add( btnChallenges ); - pos = btnChallenges.bottom(); + float left = (WIDTH - btnTalents.width() - btnChallenges.width())/3f; + + btnTalents.setPos(left, btnTalents.top()); + btnChallenges.setPos(btnTalents.right() + left, btnTalents.top()); } pos += GAP; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java index f2ddc7dcf..f6e5ec141 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndSettings.java @@ -832,7 +832,7 @@ public class WndSettings extends WndTabbed { RenderedTextBlock title = PixelScene.renderTextBlock(6); title.text(Messages.titleCase(Messages.get(LangsTab.this, "credits")), w); - title.hardlight(SHPX_COLOR); + title.hardlight(TITLE_COLOR); title.setPos((w - title.width()) / 2, 0); credits.add(title);