From ef6968b283aa1504c11b4c8307df93e553ded365 Mon Sep 17 00:00:00 2001 From: Mr Extremez Date: Wed, 19 Feb 2020 07:46:00 -0600 Subject: [PATCH] Farming Skill, Orb Charging, Battle Staff Creation, etc (#377) - Farming Skill Added - Orb charging implemented - Battle staff creation implemented - Cleaned up some code - Stuck command will now tele you from further out in wildy if you are not in combat - Fixed an issue with amulet of glory - Added forcechats for npcs at Gnome Agility Course, and for Cows, Ducks and Sheeps just like in actual osrs - Added base for God Book preaching --- 2006Redone Client/bin/.gitignore | 2 - 2006Redone Client/bin/Class13.class | Bin 9277 -> 9342 bytes 2006Redone Client/bin/Client.class | Bin 0 -> 1022 bytes 2006Redone Client/bin/Game.class | Bin 223681 -> 223688 bytes 2006Redone Client/bin/InputStream_Sub1.class | Bin 3360 -> 3356 bytes 2006Redone Client/bin/ItemDef.class | Bin 33878 -> 34213 bytes 2006Redone Client/bin/LocalGame.class | Bin 0 -> 308 bytes 2006Redone Client/bin/Main.class | Bin 1198 -> 1226 bytes 2006Redone Client/bin/Signlink.class | Bin 11629 -> 11633 bytes 2006Redone Client/bin/SoundPlayer.class | Bin 3187 -> 3102 bytes 2006Redone Client/bin/TextDrawingArea.class | Bin 9412 -> 9459 bytes 2006Redone Client/bin/TextInput.class | Bin 2549 -> 2560 bytes 2006Redone Client/bin/java.policy.applet | 7 - 2006Redone Server/data/minutes.log | 1 + .../main/java/com/rebotted/GameEngine.java | 54 +- .../game/content/combat/CombatAssistant.java | 4 +- .../game/content/consumables/Potions.java | 6 +- .../game/content/minigames/Dueling.java | 20 +- .../game/content/random/PartyRoom.java | 4 +- .../game/content/skills/SkillConstants.java | 33 + .../game/content/skills/SkillHandler.java | 28 + .../content/skills/crafting/BattleStaffs.java | 104 ++ .../content/skills/crafting/OrbCharging.java | 137 +++ .../content/skills/farming/Allotments.java | 1047 ++++++++++++++++- .../game/content/skills/farming/Bushes.java | 944 +++++++++++++++ .../game/content/skills/farming/ChopTree.java | 243 ++++ .../game/content/skills/farming/Compost.java | 545 +++++++++ .../game/content/skills/farming/Farmers.java | 274 +++++ .../game/content/skills/farming/Farming.java | 306 ++++- .../skills/farming/FarmingConstants.java | 39 +- .../content/skills/farming/FarmingTask.java | 19 + .../game/content/skills/farming/Flowers.java | 894 +++++++++++++- .../content/skills/farming/FruitTree.java | 1005 ++++++++++++++++ .../game/content/skills/farming/Herbs.java | 833 ++++++++++++- .../game/content/skills/farming/Hops.java | 933 +++++++++++++++ .../game/content/skills/farming/Patch.java | 11 - .../content/skills/farming/PatchState.java | 5 + .../game/content/skills/farming/Seedling.java | 167 +++ .../skills/farming/SpecialPlantOne.java | 886 ++++++++++++++ .../skills/farming/SpecialPlantTwo.java | 892 ++++++++++++++ .../skills/farming/ToolLeprechaun.java | 377 ++++++ .../content/skills/farming/WoodTrees.java | 983 ++++++++++++++++ .../game/dialogues/DialogueHandler.java | 150 ++- .../game/dialogues/DialogueOptions.java | 79 +- .../com/rebotted/game/items/GameItem.java | 2 +- .../com/rebotted/game/items/Inventory.java | 149 +++ .../java/com/rebotted/game/items/Item.java | 441 ++----- .../rebotted/game/items/ItemAssistant.java | 30 +- .../com/rebotted/game/items/ItemData.java | 376 ++++++ .../java/com/rebotted/game/items/UseItem.java | 6 + .../com/rebotted/game/items/impl/CapeDye.java | 8 +- .../rebotted/game/items/impl/GodBooks.java | 127 ++ .../com/rebotted/game/npcs/NpcActions.java | 27 +- .../com/rebotted/game/npcs/NpcHandler.java | 37 +- .../rebotted/game/objects/ObjectsActions.java | 11 +- .../com/rebotted/game/players/Player.java | 119 +- .../com/rebotted/game/players/Trading.java | 8 +- .../rebotted/game/shops/ShopAssistant.java | 4 +- .../java/com/rebotted/net/PacketSender.java | 26 + .../rebotted/net/packets/PacketHandler.java | 2 + .../rebotted/net/packets/impl/BankAll.java | 12 +- .../rebotted/net/packets/impl/ClickItem.java | 2 + .../net/packets/impl/ClickObject.java | 5 +- .../rebotted/net/packets/impl/Commands.java | 24 +- .../rebotted/net/packets/impl/ItemOnNpc.java | 5 + .../net/packets/impl/ItemOnObject.java | 8 - .../net/packets/impl/MagicOnFloorItems.java | 6 +- .../net/packets/impl/MagicOnObject.java | 27 + .../java/com/rebotted/tick/Scheduler.java | 59 + .../src/main/java/com/rebotted/tick/Tick.java | 151 +++ .../java/com/rebotted/world/ItemHandler.java | 2 +- 71 files changed, 12165 insertions(+), 541 deletions(-) delete mode 100644 2006Redone Client/bin/.gitignore create mode 100644 2006Redone Client/bin/Client.class create mode 100644 2006Redone Client/bin/LocalGame.class delete mode 100644 2006Redone Client/bin/java.policy.applet create mode 100644 2006Redone Server/data/minutes.log create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/SkillConstants.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/crafting/BattleStaffs.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/crafting/OrbCharging.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Bushes.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/ChopTree.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Compost.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Farmers.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FarmingTask.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FruitTree.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Hops.java delete mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Patch.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/PatchState.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Seedling.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/SpecialPlantOne.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/SpecialPlantTwo.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/ToolLeprechaun.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/WoodTrees.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/items/Inventory.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/items/ItemData.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/game/items/impl/GodBooks.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/net/packets/impl/MagicOnObject.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/tick/Scheduler.java create mode 100644 2006Redone Server/src/main/java/com/rebotted/tick/Tick.java diff --git a/2006Redone Client/bin/.gitignore b/2006Redone Client/bin/.gitignore deleted file mode 100644 index bd317d51..00000000 --- a/2006Redone Client/bin/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/Client.class -/LocalGame.class diff --git a/2006Redone Client/bin/Class13.class b/2006Redone Client/bin/Class13.class index 9b14b6ac1612bbf4279ed52b61896ea3062503c9..7e4a7ff5e3e54007aefdac02aabdee4ffc36e126 100644 GIT binary patch delta 59 zcmdn%@y}z!GCn3joy{xwF7h!(O|FvN$NHavhk<8ugPa%>1H)uXxiX-DH-k7(K#rA> Nk&%I6^Cr1&Rsc+R5f1!9QL@S0ow;+*nKLs#exH2@ki%;Y0fDZihAAzjAtVsrGY*YR!?5a^ zjqN>IRlJ@zEmJ)g2&U2%fzXm&lTic_(GfRcmh7t0s2Gmv z`RBoq+BIE)?ox*>Po$<{S^@*9kEILNvT{tTo=;c0kr0Svb8}PE{IU`B;i`syfh!$= zvQ&zhu8sj*V`jOqSt)FOD!%pj|HIQTM8Z|0$Bu~_1$&Z^iuEXxQ`UMO_vesr#|r^f(bm(FiEXtvu-s^ zYhTAhAJSE}Bh6YA8Dup~3-tSiT2f_-G>f&GBV8)W;gNt|m&$MCn(cB7gQ;{!)<4<# zDEVe|%wmp}xXN%;%P|iHhEkX3rz@VMr#ha2Lr7E|X(-w0>59V!34~L{qL;OR7aBPD z;lEYBv-U0fv*lG(_)?WEW!jdGm;M@%)ly|;RQI!oMouvn zYGXV;+D7^mQ>S=5nGin{fnUdX@|BxEd5rlZLWMct8Fn`ak2*&p5I#(*7$Zp*F~Ham zy_L&mat6pS;{D2g@3C)Zs0(}LWu4f-2jSz E01@NX4gdfE literal 0 HcmV?d00001 diff --git a/2006Redone Client/bin/Game.class b/2006Redone Client/bin/Game.class index 05fbc278442d3f90b4d28198ec818c1121a8a5e5..cc0007c954c1d6c685cffc7b8c15cb1e9f3dde78 100644 GIT binary patch delta 58677 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 NIA)#>Uo0_@_o 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

F+%uO&c_z>O8wG)$|t9^2icC21)x4Qy{M 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 diff --git a/2006Redone Client/bin/InputStream_Sub1.class b/2006Redone Client/bin/InputStream_Sub1.class index e521cf9578a715f2947da6570997cbd8de324509..64d2fa552f0ec89be5f41143ccf8439bca5801de 100644 GIT binary patch delta 28 jcmZ1=HAiX#9~&d{W`4E?HqIah5e5bZZw8jhb9h<+T+0Ro delta 32 ncmbOuwLoeE9~&e4W`4E?Hr_A>Q3eJEZw3|yP6pP=Gk976Zyp94 diff --git a/2006Redone Client/bin/ItemDef.class b/2006Redone Client/bin/ItemDef.class index 5b97712930ceec2c08707d62ad329a0af7612994..63427de60ea56c6693ba58dc6fde83db989c524c 100644 GIT binary patch literal 34213 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 delta 17209 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 K%70K^W9J`y5?8YT delta 382 zcmW-dIZpyn6ot)8DeW^Po}lEGcl7O z(dZALxAT8kxjf8GPVPDPArp33Ya9|bG4Qx zBLGQa5~K(rOyD-!bxlnZ5Oo+wD5AqyxNe)Ba-%WqE0j^)1hS=d@_O^Uq_u|CIf{8K z5JQe37fE{@jJzUn z@{FmXM|Lpnaxl|JjCU~W@jFQLvC_w8$V5@FBy{1v|@El`?kO g8~vET9xCjnf=3nmY&&4N2$!!dpujVK$UKLmKWHsag#Z8m diff --git a/2006Redone Client/bin/Signlink.class b/2006Redone Client/bin/Signlink.class index cf0ae42cac9fdb94db4e71fc7c23ebd261dbd4c6..85b31bcc877d4efb90b2a1e3f5934e950b6a9e52 100644 GIT binary patch delta 50 ucmaDG^)YJ0H8Fl^eLW)s1GA#kr2LYS)Rf7O#bN|yovlzsH~Wdpiva-ISrIh= delta 46 scmewu^)_n5H8EaEeLW)s1GA#kl>EHZ$xp>%_@$k#ki|9!iOY)t0FMz5djJ3c diff --git a/2006Redone Client/bin/SoundPlayer.class b/2006Redone Client/bin/SoundPlayer.class index f3090fc69b6c3545e3d9d8a60efcc9de062cbd4f..420335285caecf4d03e0aae54ee4c45ff5be448a 100644 GIT binary patch delta 296 zcmXAiyGjF56h+saxq8P*caazv6fyCMI_l^bSlNn|h={LBA+4491CiSpA2IQ5lmW4` z@KuSGe_~-To-qgZ+U#=g$K+;O<`8l8ZA~7 z4Ty$CqoUXzq_&#c!_*$7_BhR@vh*1j_F#mIlvrYrWky(Gj8!IBCt;IVuK8Ax>?S2i rrIgKD=}#mCw3obW^6vzM1JWt&*!@^BWjm0#Sonb~9L?iMR5krzBZ%NW@t;Pqi(X;V7#yf+< zlbwakEcq--+2emxZvB4eo^#JVom}WE6nOi7egP1N=LK3+tds|w(za2?Xuv2!6+ey4 zYtf`zpi-}HS|yxI3lY~-VSjykGqbF4?TTt}ZY|WZTIGJIN=w`y6}2AS9lPeK&0l9{ z-(kVW8Pnkc4NMY?1V}4sC!HikdPpA`B*SEsjO$&|d!qM6ABa8_eIz<3`dD;c^oaz8 zJvJKYILhf6Br%H)%%KbO=+0sRy;wp&RxpHBj9?98SjPl5Fog_a{8Ih5Aezw3jH_~# q=8_5CD-cZj{tp{ZS@huy=ZsM}xWE-|P{y4LxMN)8aFgHT!Q{Wp=SuJZ diff --git a/2006Redone Client/bin/TextDrawingArea.class b/2006Redone Client/bin/TextDrawingArea.class index 8ad89a0e0a8b50c7f969c52063bab48d7bd29bcd..cb001c145aeb2408c28f99aa0a88ed6ca467db4f 100644 GIT binary patch delta 2274 zcmY*b32+oe6n#H?%jg?pv@Tgzlk`IHriQohwy{PDWV|bIB%%>7`r&;IAK*jdpi-1N#%N_C>Hu1x z;$yOk*i03l63mXq9B47apOa0UU2Z0|sQ8L(dU++^f$STySyk0$CfRpn6|r&^KM=&s zx-Ab6Q*nkYl8CA}Yl4cHieCugiM}Z&Y~>8UTl6BbTCzVa){m?Y*?F?cL|+G9{ypb6Sj|b z&4^MFPbTBjtyl+5^tP-?W>U5$IsZwrVjVT<#ChSat*(p4W>9enYLX|NjWSPfcUMgc zrQ7zoo{Q5xc~Ia5B-3~yDT{jC(u9XXs;;)rUxR5z|Llsu2Dk=!0>wMf zO;=09L+TaLm0V{NjE0t8#$FrCPajyQrE zA_WtmAx@-{*Y(3ntRk#q^#XX$QLEPf%cU8va~L6U1uqkO(wb4knfKx~V{cBLZ(jyp z2}^y7QhbJSIKi!b zj%s{?7$u0~Bog=0Oi44Dqm8*t=C+tx?A(c-q^eCF zq-k5YYe&lJqt)n6@*6z(oxV0h$DhcdOa(ZPZfulN9=*Qez#wsAh`2FI6qHfI>%@y2 zc*v$mI>J0!)zTg@_T5Z&Q5_G_e96K>o}DFLoOaa#IVZJgEWQ(GJ3jPYO~DCx%LKrrR43Wt>6QXbTG@8)qui)?qr!Pqbk@vm0O~_nWS)xOILNz zE(vTiCASn$AixvWA08Qi3<;rw3`DkEj6Au7iVs3h8H_%1DHR`rkunrxWf)by0#O-G zg-2k9jKnM%g}E}C3SWuEQU*h=rn=Wq*)iBE8P{T$jKv-qhkbG#@AvUW=e%smHwNZ4 zILv$MSl)@$L?|+e$8|EYHy89u<(hp&hdsK| zX_s{Q*W5c1q`C9pmHF_?Jb3LLcX zGUn=4Q)*>fZBtti#48pKO+>-JD{V?&4 zSR%d5#Crm(QfUwR-S7uu3s=>t?+r4P7+%xb}q{%i%k?eFSfX)#)IeGz4T|9 zGS`SPFUyoU(`7!f*0vUthCr$*8GwfYi$M$}d@CB0Z4GY3vN*(zc-xwnF1Xc=46}HV z8!-~iZEej+w5%OasUPqIVf%&k|EM$teVjCWw zC%96x#}GI#X$F2*vk$)WxR%v@2;}u)oL1eBKk8{~{x3De)ggGvi}3E!Q7dh4dpG_R z#`7-e#sMc*^e_)Ozbl#$IaEBT#Z`kZ&lQ#5^oDlYqdmTbVd%vuysb6f!34aEoA92_ zdlZd$A88!ZZa+i|KEjgG`0Xq}DzUvJ5Y93|?kAj__jivI0jr9w%9eQ>@OGcENy6gQYF|ejkm|a(bh&jM-2ZH@axr z-elbL!~>pqFxJJ;c2w#aOU6UC&kiNyKC$U`&<@#N4G7wX9nv6oY|Qr6b#Z71BDODw zlioUwh;}i&9W{DJ-D$k;G+wc3?lieM>YU}Vg3#~|lt*o^rWx*RiB)6@t8BlL42|*G zrXASBk-Mbwz)fyJRJUOw0<1xplQ5ik6J&$*$bkR{Hd zk`9mCs)D1AW#+=*JYC_NQNa0#aRDlL3ohlY`uN<2sr&(E@Q0Yi+cBGWU=HiCfC=2e zg-9@|%`8GQ7i%L8xRZ^zTXVE?i8j-O&1}YFT#63<7*8nH$z^zk%kiAndV#C5j&6#o zt3Vwp*R8ORqtqupA%W&bx^)<}1z0hcvVT|DGGTUPuHgL}&^$rQSEB!>gG zQM`wxUz@vJoe{hXLEeoBSHoroBe({oT#IqMNBXYA6t2f~w(A<*i+Q{cN&W;s;s&&E zBUbUJ(sC2l^L}jL1Na#q#8x`k!H4i0{v6%hj6X2E1^c-buW%a<^AVijqt2GmRnl$W z=&j@R0m^mWd(<&ql{eaf$nn*7upyu2tA%@A9O-e|$6S{Gb$rPG;)lmvIrSGRi4N7{ zcGcq!ZTSgp`AN0-r*zYwRvrFQ_V1AWow$p?#yaI~;7(^oxm#un%3~bmEGu7OjMeIS Gy!gMj{Rs~M diff --git a/2006Redone Client/bin/TextInput.class b/2006Redone Client/bin/TextInput.class index 3fa6c78b6a560b6e744a9e6452feb92f5cfd37b7..937d6c996252ac5b7528d4641b836c0ce5abd9aa 100644 GIT binary patch delta 41 vcmew=+#s@{l$FtZa~Ufq6Ql0r26j>Y{|tN#Y>ey-{ER@rz_58Hdkhl**%k 0 || c.underAttackBy2 > 0); + public boolean inCombat() { + return (player.underAttackBy > 0 || player.underAttackBy2 > 0); } public void delayedHit(int i) { // npc hit delay diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/consumables/Potions.java b/2006Redone Server/src/main/java/com/rebotted/game/content/consumables/Potions.java index ad6781e4..b3744a12 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/consumables/Potions.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/consumables/Potions.java @@ -3,7 +3,7 @@ package com.rebotted.game.content.consumables; import com.rebotted.event.CycleEvent; import com.rebotted.event.CycleEventContainer; import com.rebotted.event.CycleEventHandler; -import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemData; import com.rebotted.game.items.ItemAssistant; import com.rebotted.game.players.Player; @@ -30,9 +30,9 @@ public class Potions { c.getCombatAssistant().resetPlayerAttack(); c.attackTimer++; c.getPacketSender().sendMessage( - "You drink some of your " + Item.getItemName(itemId) + "."); + "You drink some of your " + ItemData.getItemName(itemId) + "."); c.startAnimation(829); - final String item = Item.getItemName(itemId); + final String item = ItemData.getItemName(itemId); String m = ""; if (item.endsWith("(4)")) { m = "You have 3 doses of potion left."; diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/minigames/Dueling.java b/2006Redone Server/src/main/java/com/rebotted/game/content/minigames/Dueling.java index dd1aac4d..5d0977f8 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/minigames/Dueling.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/minigames/Dueling.java @@ -6,7 +6,7 @@ import com.rebotted.GameEngine; import com.rebotted.game.content.combat.prayer.PrayerDrain; import com.rebotted.game.content.minigames.castlewars.CastleWars; import com.rebotted.game.items.GameItem; -import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemData; import com.rebotted.game.items.ItemAssistant; import com.rebotted.game.items.impl.RareProtection; import com.rebotted.game.players.Client; @@ -243,7 +243,7 @@ public class Dueling { return false; } changeDuelStuff(); - if (!Item.itemStackable[itemID]) { + if (!ItemData.itemStackable[itemID]) { for (int a = 0; a < amount; a++) { if (player.getItemAssistant().playerHasItem(itemID, 1)) { stakedItems.add(new GameItem(itemID, 1)); @@ -260,7 +260,7 @@ public class Dueling { player.getPacketSender().sendFrame126("", 6684); o.getPacketSender().sendFrame126("", 6684); } - if (Item.itemStackable[itemID] || Item.itemIsNote[itemID]) { + if (ItemData.itemStackable[itemID] || ItemData.itemIsNote[itemID]) { boolean found = false; for (GameItem item : stakedItems) { if (item.id == itemID) { @@ -314,7 +314,7 @@ public class Dueling { o.getDueling().declineDuel(); return false; } - if (Item.itemStackable[itemID]) { + if (ItemData.itemStackable[itemID]) { if (player.getItemAssistant().freeSlots() - 1 < player.duelSpaceReq) { player.getPacketSender().sendMessage( "You have too many rules set to remove that item."); @@ -324,7 +324,7 @@ public class Dueling { changeDuelStuff(); boolean goodSpace = true; - if (!Item.itemStackable[itemID]) { + if (!ItemData.itemStackable[itemID]) { for (int a = 0; a < amount; a++) { for (GameItem item : stakedItems) { if (item.id == itemID) { @@ -423,7 +423,7 @@ public class Dueling { } String itemId = ""; for (GameItem item : stakedItems) { - if (Item.itemStackable[item.id] || Item.itemIsNote[item.id]) { + if (ItemData.itemStackable[item.id] || ItemData.itemIsNote[item.id]) { itemId += ItemAssistant.getItemName(item.id) + " x " + Misc.format(item.amount) + "\\n"; } else { @@ -433,7 +433,7 @@ public class Dueling { player.getPacketSender().sendFrame126(itemId, 6516); itemId = ""; for (GameItem item : o.getDueling().stakedItems) { - if (Item.itemStackable[item.id] || Item.itemIsNote[item.id]) { + if (ItemData.itemStackable[item.id] || ItemData.itemIsNote[item.id]) { itemId += ItemAssistant.getItemName(item.id) + " x " + Misc.format(item.amount) + "\\n"; } else { @@ -651,7 +651,7 @@ public class Dueling { public void claimStakedItems() { for (GameItem item : otherStakedItems) { if (item.id > 0 && item.amount > 0) { - if (Item.itemStackable[item.id]) { + if (ItemData.itemStackable[item.id]) { if (!player.getItemAssistant().addItem(item.id, item.amount)) { GameEngine.itemHandler.createGroundItem(player, item.id, player.getX(), player.getY(), item.amount, player.getId()); @@ -669,7 +669,7 @@ public class Dueling { } for (GameItem item : stakedItems) { if (item.id > 0 && item.amount > 0) { - if (Item.itemStackable[item.id]) { + if (ItemData.itemStackable[item.id]) { if (!player.getItemAssistant().addItem(item.id, item.amount)) { GameEngine.itemHandler.createGroundItem(player, item.id, player.getX(), player.getY(), item.amount, player.getId()); @@ -713,7 +713,7 @@ public class Dueling { if (item.amount < 1) { continue; } - if (Item.itemStackable[item.id] || Item.itemIsNote[item.id]) { + if (ItemData.itemStackable[item.id] || ItemData.itemIsNote[item.id]) { player.getItemAssistant().addItem(item.id, item.amount); } else { player.getItemAssistant().addItem(item.id, 1); diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/random/PartyRoom.java b/2006Redone Server/src/main/java/com/rebotted/game/content/random/PartyRoom.java index 92f680b2..44742f1e 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/random/PartyRoom.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/random/PartyRoom.java @@ -5,7 +5,7 @@ import java.util.ArrayList; import java.util.Random; import com.rebotted.GameConstants; import com.rebotted.GameEngine; -import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemData; import com.rebotted.game.objects.Objects; import com.rebotted.game.players.Player; @@ -99,7 +99,7 @@ public class PartyRoom { public static void accept(Player c) { for (int x = 0; x < c.party.length; x++) { if (c.partyN[x] > 0) { - if (Item.itemStackable[c.party[x]]) { + if (ItemData.itemStackable[c.party[x]]) { int slot = arraySlot(roomItems, c.party[x]); if (slot < 0) { c.getPacketSender().sendMessage( diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/SkillConstants.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/SkillConstants.java new file mode 100644 index 00000000..db323c88 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/SkillConstants.java @@ -0,0 +1,33 @@ +package com.rebotted.game.content.skills; +/** + * SkillConstants.java + * @author Andrew (Mr Extremez) + */ + +public enum SkillConstants { + + ATTACK(true), DEFENCE(true), STRENGTH(true), HITPOINTS(true), RANGE(true), + PRAYER(true), MAGIC(true), COOKING(true), WOODCUTTING(true), FLETCHING(true), + FISHING(true), FIREMAKING(true), CRAFTING(true), SMITHING(true), MINING(true), + HERBLORE(true), AGILITY(true), THIEVING(true), SLAYER(true), FARMING(true), RUNECRAFTING(true); + + private SkillConstants(boolean skillEnabled) { + this.skillEnabled = skillEnabled; + } + + private boolean skillEnabled; + + public static boolean getEnabled(int id) { + for (final SkillConstants skillConstants : SkillConstants.values()) { + if (skillConstants.ordinal() == id && skillConstants.skillEnabled == true) { + return true; + } + } + return false; + } + + public static String getName(SkillConstants skillConstants) { + return "The " + skillConstants.name().toLowerCase() + " skill is currently disabled"; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/SkillHandler.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/SkillHandler.java index 4fef6c09..429a365e 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/SkillHandler.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/SkillHandler.java @@ -1,5 +1,7 @@ package com.rebotted.game.content.skills; +import java.util.Random; + import com.rebotted.event.CycleEventHandler; import com.rebotted.game.content.skills.cooking.Cooking; import com.rebotted.game.content.skills.core.Fishing; @@ -28,6 +30,13 @@ public class SkillHandler { RUNECRAFTING = true, THIEVING = true, WOODCUTTING = true, PRAYER = true, FLETCHING = true, CRAFTING = true, MAGIC = true, FARMING = false, SLAYER = true, SMITHING = true; + + public static final String[] skillNames = { "Attack", "Defence", + "Strength", "Hitpoints", "Range", "Prayer", "Magic", "Cooking", + "Woodcutting", "Fletching", "Fishing", "Firemaking", "Crafting", + "Smithing", "Mining", "Herblore", "Agility", "Thieving", "Slayer", + "Farming", "Runecrafting" }; + public static boolean isSkilling(Player player) { if (player.playerSkilling[10] || player.playerStun || player.playerSkilling[12] @@ -158,6 +167,16 @@ public class SkillHandler { } } } + + public static boolean hasRequiredLevel(final Player player, int skillId, + int lvlReq, String event) { + if (player.playerLevel[skillId] < lvlReq) { + player.getPacketSender().sendMessage("You need at least " + lvlReq + " " + + skillNames[skillId] + " to " + event + "."); + return false; + } + return true; + } public static boolean hasRequiredLevel(final Player c, int id, int lvlReq, String skill, String event) { @@ -169,6 +188,15 @@ public class SkillHandler { } return true; } + + public static boolean skillCheck(int level, int levelRequired, int itemBonus) { + double chance = 0.0; + double baseChance = levelRequired < 11 ? 15 : levelRequired < 51 ? 10 + : 5;// Math.pow(10d-levelRequired/10d, 2d)/2d; + chance = baseChance + ((level - levelRequired) / 2d) + + (itemBonus / 10d); + return chance >= (new Random().nextDouble() * 100.0); + } public static String getLine(Player c) { return c.below459 ? "\\n\\n\\n\\n" : "\\n\\n\\n\\n\\n"; diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/crafting/BattleStaffs.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/crafting/BattleStaffs.java new file mode 100644 index 00000000..13cfd82c --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/crafting/BattleStaffs.java @@ -0,0 +1,104 @@ +package com.rebotted.game.content.skills.crafting; + +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.players.Player; + +/** + * Battle Staff making + * @author Andrew (Mr Extremez) + */ +public class BattleStaffs { + + public static enum battleStaffs { + + AIR(573, 66, 138, 1397), + FIRE(569, 62, 125, 1393), + EARTH(575, 58, 113, 1399), + WATER(571, 54, 100, 1395); + + private int orb, levelReq, xpRecieved, battlestaff; + + private battleStaffs(final int orb, final int levelReq, final int xpRecieved, final int battlestaff) { + this.orb = orb; + this.levelReq = levelReq; + this.xpRecieved = xpRecieved; + this.battlestaff = battlestaff; + } + + public int getOrb() { + return orb; + } + + public int getLevelReq() { + return levelReq; + } + + public int getXP() { + return xpRecieved; + } + + public int getBattlestaff() { + return battlestaff; + } + } + + public static void makeBattleStaff(Player player, int itemUsed, int usedWith) { + for (final battleStaffs b : battleStaffs.values()) { + if ((itemUsed == b.getOrb() && usedWith == 1391) || (itemUsed == 1391 && usedWith == b.getOrb())) { + if (player.getItemAssistant().playerHasItem(1391) && player.getItemAssistant().playerHasItem(b.getOrb())) { + if (player.isCrafting == true) { + return; + } + if (player.playerLevel[12] < b.getLevelReq()) { + player.getPacketSender().sendMessage("You need level " + b.getLevelReq() + " crafting to do that."); + return; + } + player.getPacketSender().closeAllWindows(); + player.isCrafting = true; + player.skillAmount = player.getItemAssistant().getItemAmount(b.getOrb()); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (player.isCrafting == true && player != null) { + if (!player.getItemAssistant().playerHasItem(1391, 1)) { + player.getPacketSender().sendMessage("You have run out of battlestaffs."); + container.stop(); + return; + } + if (!player.getItemAssistant().playerHasItem(b.getOrb(), 1)) { + player.getPacketSender().sendMessage("You have run out of orbs."); + container.stop(); + return; + } + if (player.skillAmount == 0) { + container.stop(); + return; + } + player.getItemAssistant().deleteItem(1391, 1); + player.getItemAssistant().deleteItem(b.getOrb(), 1); + player.getItemAssistant().addItem(b.getBattlestaff(), 1); + player.getPlayerAssistant().addSkillXP((int) b.getXP(), 6); + player.skillAmount--; + if (!player.getItemAssistant().playerHasItem(1391) || !player.getItemAssistant().playerHasItem(b.getOrb())) { + container.stop(); + return; + } + } else { + container.stop(); + } + } + + @Override + public void stop() { + player.isCrafting = false; + } + }, 2); + } + } + } + } + + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/crafting/OrbCharging.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/crafting/OrbCharging.java new file mode 100644 index 00000000..afd9f9c2 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/crafting/OrbCharging.java @@ -0,0 +1,137 @@ +package com.rebotted.game.content.skills.crafting; + +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.items.ItemAssistant; +import com.rebotted.game.players.Player; + +public class OrbCharging { + + public static void chargeOrbs(final Player player, final int spellId, final int objectId) { + if (player.isCrafting == true) { + return; + } + for (final Orb l : Orb.values()) { + if (objectId == l.getObjectId(objectId)) { + if (l.getSpell() == spellId) { + if (!player.getItemAssistant().playerHasItem(567, 1)) { + player.getPacketSender().sendMessage("You need 1 " + ItemAssistant.getItemName(567).toLowerCase() + " to make " + + ItemAssistant.getItemName(l.getProduct()).toLowerCase() + "."); + player.getPacketSender().closeAllWindows(); + return; + } + player.getPacketSender().closeAllWindows(); + player.isCrafting = true; + player.skillAmount = l.getAmount(objectId); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (player.isCrafting == true && player != null) { + if (!player.getItemAssistant().playerHasItem(567, 1)) { + player.getPacketSender().sendMessage("You have run out of unpowered orbs."); + container.stop(); + return; + } + if (!player.getCombatAssistant().checkMagicReqs(l.getSpellConfig())) { + container.stop(); + return; + } + if (player.skillAmount == 0) { + container.stop(); + return; + } + player.startAnimation(726); + player.gfx100(l.getOrbGfx()); + player.getItemAssistant().deleteItem(567, 1); + player.getItemAssistant().addItem(l.getProduct(), 1); + player.getPlayerAssistant().addSkillXP((int) l.getXP(), 6); + player.skillAmount--; + if (!player.getItemAssistant().playerHasItem(567, 1)) { + container.stop(); + return; + } + } else { + container.stop(); + } + } + + @Override + public void stop() { + player.isCrafting = false; + } + }, 3); + } + } + } + } + + public enum Orb { + AIR(new int[][] { { 2152, 28 } }, 1058, 567, 573, 66, 76, 150, 93), + FIRE(new int[][] { { 2153, 28 }}, 1056, 567, 569, 62, 73, 152, 92), + EARTH(new int[][] { { 2150, 28} }, 1054, 567, 575, 58, 70, 151, 91), + WATER(new int[][] { { 2151, 28 } }, 1051, 567, 571, 54, 66, 149, 90); + + private int[][] objectId; + private int spellId, orb, product, level, gfx, spellConfig; + private double xp; + + private Orb(final int[][] objectId, final int spellId, final int orb, final int product, final int level, final double xp, final int gfx, final int spellConfig) { + this.objectId = objectId; + this.spellId = spellId; + this.orb = orb; + this.product = product; + this.level = level; + this.xp = xp; + this.gfx = gfx; + this.spellConfig = spellConfig; + } + + public int getObjectId(final int object) { + for (int i = 0; i < objectId.length; i++) { + if (object == objectId[i][0]) { + return objectId[i][0]; + } + } + return -1; + } + + public int getAmount(final int object) { + for (int i = 0; i < objectId.length; i++) { + if (object == objectId[i][0]) { + return objectId[i][1]; + } + } + return -1; + } + + public int getSpell() { + return spellId; + } + + public int getOrb() { + return orb; + } + + public int getProduct() { + return product; + } + + public int getLevel() { + return level; + } + + public double getXP() { + return xp; + } + + public int getOrbGfx() { + return gfx; + } + + public int getSpellConfig() { + return spellConfig; + } + } + +} \ No newline at end of file diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Allotments.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Allotments.java index 3f30a3b7..364fc0b1 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Allotments.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Allotments.java @@ -1,25 +1,1046 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ package com.rebotted.game.content.skills.farming; -import com.rebotted.game.players.Player; - /** - * Allotments - * @author Andrew (Mr Extremez) + * + * @author ArrowzFtw */ +import java.awt.Point; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; +/** + * Created by IntelliJ IDEA. User: vayken Date: 24/02/12 Time: 20:34 To change + * this template use File | Settings | File Templates. + */ public class Allotments { - - - private static final int[] ALLOTMENT = {8550, 8551, 8552, 8553}; - - public static boolean isAllotment(Player player, int objectType) { - for (int i = 0; i < ALLOTMENT.length; i++) { - if (objectType == ALLOTMENT[i]) { - return true; + + private Player player; + + // set of global constants for Farming + + private static final int START_HARVEST_AMOUNT = 3; + private static final int END_HARVEST_AMOUNT = 56; + + private static final double WATERING_CHANCE = 0.5; + private static final double COMPOST_CHANCE = 0.9; + private static final double SUPERCOMPOST_CHANCE = 0.7; + private static final double CLEARING_EXPERIENCE = 4; + + public Allotments(Player player) { + this.player = player; + } + + // Farming data + public int[] allotmentStages = new int[8]; + public int[] allotmentSeeds = new int[8]; + public int[] allotmentHarvest = new int[8]; + public int[] allotmentState = new int[8]; + public long[] allotmentTimer = new long[8]; + public double[] diseaseChance = { 1, 1, 1, 1, 1, 1, 1, 1 }; + public boolean[] allotmentWatched = { false, false, false, false, false, + false, false, false }; + public boolean[] hasFullyGrown = { false, false, false, false, false, + false, false, false }; + + /* set of the constants for the patch */ + + // states - 2 bits plant - 6 bits + public static final int GROWING = 0x00; + public static final int WATERED = 0x01; + public static final int DISEASED = 0x02; + public static final int DEAD = 0x03; + + public static final int FALADOR_AND_CATHERBY_CONFIG = 504; + public static final int ARDOUGNE_AND_PHASMATYS_CONFIG = 505; + + /* This is the enum holding the seeds info */ + + public enum AllotmentData { + + POTATO(5318, 1942, 5096, 3, 1, new int[] { 6032, 2 }, 4, 0.30, 8, 9.5, + 0x06, 0x0c), ONION(5319, 1957, 5096, 3, 5, + new int[] { 5438, 1 }, 5, 0.30, 9.5, 10.5, 0x0d, 0x13), CABBAGE( + 5324, 1965, 5097, 3, 7, new int[] { 5458, 1 }, 5, 0.25, 10, + 11.5, 0x14, 0x1a), TOMATO(5322, 1982, 5096, 3, 12, new int[] { + 5478, 2 }, 5, 0.25, 12.5, 14, 0x1b, 0x21), SWEETCORN(5320, + 5986, 6059, 3, 20, new int[] { 5931, 10 }, 5, 0.20, 17, 19, + 0x22, 0x2a), STRAWBERRY(5323, 5504, -1, 3, 31, new int[] { + 5386, 1 }, 6, 0.20, 26, 29, 0x2b, 0x33), WATERMELON(5321, 5982, + 5098, 3, 47, new int[] { 5970, 10 }, 7, 0.20, 48.5, 54.5, 0x34, + 0x3e); + + private int seedId; + private int harvestId; + private int flowerProtect; + private int seedAmount; + private int levelRequired; + private int[] paymentToWatch; + private int growthTime; + private double diseaseChance; + private double plantingXp; + private double harvestXp; + private int startingState; + private int endingState; + + private static Map seeds = new HashMap(); + + static { + for (AllotmentData data : AllotmentData.values()) { + seeds.put(data.seedId, data); } } + + AllotmentData(int seedId, int harvestId, int flowerProtect, + int seedAmount, int levelRequired, int[] paymentToWatch, + int growthTime, double diseaseChance, double plantingXp, + double harvestXp, int startingState, int endingState) { + this.seedId = seedId; + this.harvestId = harvestId; + this.flowerProtect = flowerProtect; + this.seedAmount = seedAmount; + this.levelRequired = levelRequired; + this.paymentToWatch = paymentToWatch; + this.growthTime = growthTime; + this.diseaseChance = diseaseChance; + this.plantingXp = plantingXp; + this.harvestXp = harvestXp; + this.startingState = startingState; + this.endingState = endingState; + } + + public static AllotmentData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public int getHarvestId() { + return harvestId; + } + + public int getFlowerProtect() { + return flowerProtect; + } + + public int getSeedAmount() { + return seedAmount; + } + + public int getLevelRequired() { + return levelRequired; + } + + public int[] getPaymentToWatch() { + return paymentToWatch; + } + + public int getGrowthTime() { + return growthTime; + } + + public double getDiseaseChance() { + return diseaseChance; + } + + public double getPlantingXp() { + return plantingXp; + } + + public double getHarvestXp() { + return harvestXp; + } + + public int getStartingState() { + return startingState; + } + + public int getEndingState() { + return endingState; + } + } + + /* This is the enum data about the different patches */ + + public enum AllotmentFieldsData { + + CATHERBY_NORTH(0, new Point[] { new Point(2805, 3466), + new Point(2806, 3468), new Point(2805, 3467), + new Point(2814, 3468) }, 2324), + + CATHERBY_SOUTH(1, new Point[] { new Point(2805, 3459), + new Point(2806, 3461), new Point(2802, 3459), + new Point(2814, 3460) }, 2324), + + FALADOR_NORTH_WEST(2, new Point[] { new Point(3050, 3307), + new Point(3051, 3312), new Point(3050, 3311), + new Point(3054, 3312) }, 2323), + + FALADOR_SOUTH_EAST(3, new Point[] { new Point(3055, 3303), + new Point(3059, 3304), new Point(3058, 3303), + new Point(3059, 3308) }, 2323), + + PHASMATYS_NORTH_WEST(4, new Point[] { new Point(3597, 3525), + new Point(3598, 3530), new Point(3597, 3529), + new Point(3601, 3530) }, 2326), + + PHASMATYS_SOUTH_EAST(5, new Point[] { new Point(3602, 3521), + new Point(3606, 3522), new Point(3605, 3521), + new Point(3606, 3526) }, 2326), + + ARDOUGNE_NORTH(6, new Point[] { new Point(2662, 3377), + new Point(2663, 3379), new Point(2662, 3378), + new Point(2671, 3379) }, 2325), + + ARDOUGNE_SOUTH(7, new Point[] { new Point(2662, 3370), + new Point(2663, 3372), new Point(2662, 3370), + new Point(2671, 3371) }, 2325); + + private int allotmentIndex; + private Point[] allotmentPosition; + private int farmerBelonging; + + AllotmentFieldsData(int allotmentIndex, Point[] allotmentPosition, + int farmerBelonging) { + this.allotmentIndex = allotmentIndex; + this.allotmentPosition = allotmentPosition; + this.farmerBelonging = farmerBelonging; + } + + public static AllotmentFieldsData forIdPosition(int x, int y) { + for (AllotmentFieldsData allotmentFieldsData : AllotmentFieldsData + .values()) { + if (FarmingConstants.inRangeArea( + allotmentFieldsData.getAllotmentPosition()[0], + allotmentFieldsData.getAllotmentPosition()[1], x, y) + || FarmingConstants.inRangeArea( + allotmentFieldsData.getAllotmentPosition()[2], + allotmentFieldsData.getAllotmentPosition()[3], + x, y)) { + return allotmentFieldsData; + } + } + return null; + } + + public static ArrayList listIndexProtected(int npcId) { + ArrayList array = new ArrayList(); + for (AllotmentFieldsData allotmentFieldsData : AllotmentFieldsData + .values()) { + if (allotmentFieldsData.getFarmerBelonging() == npcId) + array.add(allotmentFieldsData.allotmentIndex); + } + return array; + + } + + public int getAllotmentIndex() { + return allotmentIndex; + } + + public Point[] getAllotmentPosition() { + return allotmentPosition; + } + + public int getFarmerBelonging() { + return farmerBelonging; + } + } + + /* This is the enum that hold the different data for inspecting the plant */ + + public enum InspectData { + POTATOES(5318, new String[][] { + { "The potato seeds have only just been planted." }, + { "The potato plants have grown to double their", + "previous height." }, + { "The potato plants now are the same height as the", + "surrounding weeds." }, + { "The potato plants now spread their branches wider,", + "not growing as much as before." }, + { "The potato plants are ready to harvest. A white", + "flower at the top of each plant opens up." } }), ONIONS( + 5319, new String[][] { + { "The onion seeds have only just been planted." }, + { "The onions are partially visible and the stems", + "have grown." }, + { "The top of the onion of the onion plant is clear", + "above the ground and the onion is white." }, + { "The onion plant is slightly larger than before and", + "the onion is cream coloured." }, + { "The onion stalks are larger than before and the", + "onion is now light and brown coloured." } }), CABBAGES( + 5324, + new String[][] { + { "The cabbage seeds have only just been planted,", + "the cabbages are small and bright green." }, + { "The cabbages are much larger, with more leaves", + "surrounding the head." }, + { "The cabbages are larger than before, and textures", + "of leaves are now easily observable." }, + { "The cabbage head has swollen larger, and the", + "surrounding leaves are more close to the ground." }, + { "The cabbage plants are ready to harvest. The", + "centre of each cabbage head is light green coloured." } }), TOMATOES( + 5322, + new String[][] { + { "The tomato seeds have only just been planted." }, + { "The tomato plants grow twice as large as before." }, + { "The tomato plants grow larger, and small green", + "tomatoes are now observable." }, + { + "The tomato plants grow thicker to hold up the", + "weight of the tomatoes. The tomatoes are now light", + "orange and slightly larger on the plant." }, + { + "The tomato plants are ready to harvest. The tomato", + "plants leaves are larger and the tomatoes are", + "ripe red." } }), SWEETCORNS( + 5320, + new String[][] { + { "The sweetcorn plants have only just been planted." }, + { "The sweetcorn plants are waist tall now and are", + "leafy." }, + { "The sweetcorn plants are slightly taller than", + "before and slightly thicker." }, + { "The sweetcorn leaves are larger at the base, and", + "the plants are slightly taller." }, + { "Closed corn cobs are now observable on the", + "sweetcorn plants." }, + { "The sweetcorn plants are ready to harvest. The", + "corn cobs are open and visibly yellow." } }), STRAWBERRIES( + 5323, + new String[][] { + { "The strawberry seeds have only just been planted." }, + { "The strawberry plants have more leaves than before." }, + { "The strawberry plants have even more leaves and is", + "slightly taller than before." }, + { "Each strawberry plant has opened one white", + "flower each." }, + { "The strawberry plants are slightly larger, and", + "have small strawberries visible at their bases." }, + { "The strawberry plants are slightly larger, opened", + "a second flower each, and have more strawberries." }, + { "The strawberry plants are ready to harvest. The", + "strawberries are almost as large as the flowers." } }), WATERMELONS( + 5321, + new String[][] { + { "The watermelon seeds have only just been planted." }, + { "The watermelon vines have grown longer than before." }, + { "The watermelon vines have grown longer than before." }, + { "The watermelon vines have started to curl, ", + "and another vine has sprouted from the centre." }, + { + "The watermelon vines have continued growing longer,", + "and another vine has sprouted." }, + { "Small watermelons are visibly growing on the vines now." }, + { "The watermelons on the vines have grown larger than before." }, + { "The watermelon plants are ready to harvest. ", + "The watermelons on the vines are large and ripe." } }); + + private int seedId; + private String[][] messages; + + private static Map seeds = new HashMap(); + + static { + for (InspectData data : InspectData.values()) { + seeds.put(data.seedId, data); + } + } + + InspectData(int seedId, String[][] messages) { + this.seedId = seedId; + this.messages = messages; + } + + public static InspectData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public String[][] getMessages() { + return messages; + } + } + + /* update all the patch states */ + + public void updateAllotmentsStates() { + // catherby north - catherby south - falador north west - falador south + // east - phasmatys north west - phasmatys south east - ardougne north - + // ardougne south + int[] configValues = new int[allotmentStages.length]; + + int configValue; + for (int i = 0; i < allotmentStages.length; i++) { + configValues[i] = getConfigValue(allotmentStages[i], + allotmentSeeds[i], allotmentState[i], i); + } + + configValue = (configValues[0] << 16) + (configValues[1] << 8 << 16) + + configValues[2] + (configValues[3] << 8); + player.getPacketSender().sendConfig(FALADOR_AND_CATHERBY_CONFIG, configValue); + + configValue = configValues[4] << 16 | configValues[5] << 8 << 16 + | configValues[6] | configValues[7] << 8; + player.getPacketSender().sendConfig(ARDOUGNE_AND_PHASMATYS_CONFIG, configValue); + + } + + /* getting the different config values */ + + public int getConfigValue(int allotmentStage, int seedId, int plantState, + int index) { + AllotmentData allotmentData = AllotmentData.forId(seedId); + switch (allotmentStage) { + case 0:// weed + return (GROWING << 6) + 0x00; + case 1:// weed cleared + return (GROWING << 6) + 0x01; + case 2: + return (GROWING << 6) + 0x02; + case 3: + return (GROWING << 6) + 0x03; + } + if (allotmentData == null) { + return -1; + } + if (allotmentData.getEndingState() == allotmentData.getStartingState() + + allotmentStage - 1) { + hasFullyGrown[index] = true; + } + + return (getPlantState(plantState) << 6) + + allotmentData.getStartingState() + allotmentStage - 4; + } + + /* getting the plant states */ + + public int getPlantState(int plantState) { + switch (plantState) { + case 0: + return GROWING; + case 1: + return WATERED; + case 2: + return DISEASED; + case 3: + return DEAD; + } + return -1; + } + + /* calculating the disease chance and making the plant grow */ + + public void doCalculations() { + for (int i = 0; i < allotmentSeeds.length; i++) { + AllotmentData allotmentData = AllotmentData + .forId(allotmentSeeds[i]); + if (allotmentData == null) { + continue; + } + /** + * Grow back weeds + */ + if (allotmentStages[i] > 0 && allotmentStages[i] <= 3 + && GameEngine.getMinutesCounter() - allotmentTimer[i] >= 5) { + allotmentStages[i]--; + allotmentTimer[i] = GameEngine.getMinutesCounter(); + updateAllotmentsStates(); + } + + int nbStates = allotmentData.getEndingState() + - allotmentData.getStartingState(); + long growth = allotmentData.getGrowthTime(); + //double cycleTime = (double) (growth / nbStates); + long difference = GameEngine.getMinutesCounter() + - allotmentTimer[i]; + int state = (int) (difference * nbStates / growth); + if (allotmentTimer[i] == 0 || allotmentState[i] == 3 + || state > nbStates) { + continue; + } + if (4 + state != allotmentStages[i]) { + allotmentStages[i] = 4 + state; + if (allotmentStages[i] <= 4 + state) + for (int j = allotmentStages[i]; j <= 4 + state; j++) + doStateCalculation(i); + updateAllotmentsStates(); + } + } + } + + public void modifyStage(int i) { + AllotmentData bushesData = AllotmentData.forId(allotmentSeeds[i]); + if (bushesData == null) + return; + long difference = GameEngine.getMinutesCounter() - allotmentTimer[i]; + long growth = bushesData.getGrowthTime(); + int nbStates = bushesData.getEndingState() + - bushesData.getStartingState(); + int state = (int) (difference * nbStates / growth); + allotmentStages[i] = 4 + state; + updateAllotmentsStates(); + + } + + /* calculations about the diseasing chance */ + + public void doStateCalculation(int index) { + if (allotmentState[index] == 3) { + return; + } + // if the patch is diseased, it dies, if its watched by a farmer, it + // goes back to normal + if (allotmentState[index] == 2) { + if (allotmentWatched[index]) { + allotmentState[index] = 0; + AllotmentData allotmentData = AllotmentData + .forId(allotmentSeeds[index]); + if (allotmentData == null) + return; + int difference = allotmentData.getEndingState() + - allotmentData.getStartingState(); + int growth = allotmentData.getGrowthTime(); + allotmentTimer[index] += (growth / difference); + modifyStage(index); + } else { + allotmentState[index] = 3; + } + } + + if (allotmentState[index] == 1) { + diseaseChance[index] *= 2; + allotmentState[index] = 0; + } + + if (allotmentState[index] == 5 && allotmentStages[index] != 3) { + allotmentState[index] = 0; + } + + if (allotmentState[index] == 0 && allotmentStages[index] >= 5 + && !hasFullyGrown[index]) { + // handleFlowerProtection(index); + } + } + + /* watering the patch */ + + public boolean waterPatch(int objectX, int objectY, int itemId) { + final AllotmentFieldsData allotmentFieldsData = AllotmentFieldsData + .forIdPosition(objectX, objectY); + if (allotmentFieldsData == null) { + return false; + } + AllotmentData allotmentData = AllotmentData + .forId(allotmentSeeds[allotmentFieldsData.getAllotmentIndex()]); + if (allotmentData == null) { + return false; + } + if (allotmentState[allotmentFieldsData.getAllotmentIndex()] == 1 + || allotmentStages[allotmentFieldsData.getAllotmentIndex()] <= 1 + || allotmentStages[allotmentFieldsData.getAllotmentIndex()] == allotmentData + .getEndingState() + - allotmentData.getStartingState() + + 4) { + player.getPacketSender().sendMessage("This patch doesn't need watering."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(itemId == 5333 ? itemId - 2 : itemId - 1, 1); + + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a seed dibber to plant seed here."); + return true; + } + player.getPacketSender().sendMessage("You water the patch."); + player.startAnimation( + FarmingConstants.WATERING_CAN_ANIM); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[allotmentFieldsData.getAllotmentIndex()] *= WATERING_CHANCE; + allotmentState[allotmentFieldsData.getAllotmentIndex()] = 1; + container.stop(); + } + + @Override + public void stop() { + updateAllotmentsStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + + } + }, 5); + return true; + } + + /* clearing the patch with a rake of a spade */ + + public boolean clearPatch(int objectX, int objectY, int itemId) { + final AllotmentFieldsData allotmentFieldsData = AllotmentFieldsData + .forIdPosition(objectX, objectY); + int finalAnimation; + int finalDelay; + if (allotmentFieldsData == null + || (itemId != FarmingConstants.RAKE && itemId != FarmingConstants.SPADE)) { + return false; + } + if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] == 3) { + return true; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] <= 3) { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a rake to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.RAKING_ANIM; + finalDelay = 5; + } + } else { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.SPADE_ANIM; + finalDelay = 3; + } + } + final int animation = finalAnimation; + player.stopPlayer(true); + player.startAnimation(animation); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.startAnimation(animation); + if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] <= 2) { + allotmentStages[allotmentFieldsData.getAllotmentIndex()]++; + player.getItemAssistant().addItem(6055, 1); + } else { + allotmentStages[allotmentFieldsData.getAllotmentIndex()] = 3; + container.stop(); + } + player.getPlayerAssistant().addSkillXP(CLEARING_EXPERIENCE, SkillConstants.FARMING.ordinal()); + allotmentTimer[allotmentFieldsData.getAllotmentIndex()] = GameEngine + .getMinutesCounter(); + updateAllotmentsStates(); + if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] == 3) { + container.stop(); + return; + } + } + + @Override + public void stop() { + resetAllotments(allotmentFieldsData.getAllotmentIndex()); + player.getPacketSender().sendMessage("You clear the patch."); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + + } + }, finalDelay); + return true; + + } + + /* planting the seeds */ + + public boolean plantSeed(int objectX, int objectY, final int seedId) { + final AllotmentFieldsData allotmentFieldsData = AllotmentFieldsData + .forIdPosition(objectX, objectY); + final AllotmentData allotmentData = AllotmentData.forId(seedId); + if (allotmentFieldsData == null || allotmentData == null) { + return false; + } + if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] != 3) { + player.getPacketSender().sendMessage("You can't plant a seed here."); + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (allotmentData.getLevelRequired() > player.playerLevel[SkillConstants.FARMING.ordinal()]) { + player.getDialogueHandler().sendStatement("You need a farming level of " + + allotmentData.getLevelRequired() + + " to plant this seed."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SEED_DIBBER)) { + player.getDialogueHandler().sendStatement( + "You need a seed dibber to plant seed here."); + return true; + } + if (player.getItemAssistant().getItemAmount(allotmentData.getSeedId()) < allotmentData + .getSeedAmount()) { + player.getDialogueHandler().sendStatement( "You need atleast " + + allotmentData.getSeedAmount() + " seeds to plant here."); + return true; + } + player.startAnimation(FarmingConstants.SEED_DIBBING); + allotmentStages[allotmentFieldsData.getAllotmentIndex()] = 4; + player.getItemAssistant().deleteItem(seedId, allotmentData.getSeedAmount()); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + allotmentState[allotmentFieldsData.getAllotmentIndex()] = 0; + allotmentSeeds[allotmentFieldsData.getAllotmentIndex()] = seedId; + allotmentTimer[allotmentFieldsData.getAllotmentIndex()] = GameEngine + .getMinutesCounter(); + player.getPlayerAssistant().addSkillXP(allotmentData.getPlantingXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateAllotmentsStates(); + player.stopPlayer(false); + } + }, 3); + return true; + } + + /* harvesting the plant resulted */ + + public boolean harvest(int objectX, int objectY) { + final AllotmentFieldsData allotmentFieldsData = AllotmentFieldsData + .forIdPosition(objectX, objectY); + if (allotmentFieldsData == null) { + return false; + } + final AllotmentData allotmentData = AllotmentData + .forId(allotmentSeeds[allotmentFieldsData.getAllotmentIndex()]); + if (allotmentData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to harvest here."); + return true; + } + player.startAnimation(FarmingConstants.SPADE_ANIM); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (allotmentHarvest[allotmentFieldsData.getAllotmentIndex()] == 0) { + allotmentHarvest[allotmentFieldsData.getAllotmentIndex()] = 1 + (START_HARVEST_AMOUNT + Misc + .random(END_HARVEST_AMOUNT - START_HARVEST_AMOUNT)) * (1); + } + if (allotmentHarvest[allotmentFieldsData.getAllotmentIndex()] == 1) { + resetAllotments(allotmentFieldsData.getAllotmentIndex()); + allotmentStages[allotmentFieldsData.getAllotmentIndex()] = 3; + allotmentTimer[allotmentFieldsData.getAllotmentIndex()] = GameEngine + .getMinutesCounter(); + container.stop(); + return; + } + if (player.getItemAssistant().freeSlots() <= 0) { + container.stop(); + return; + } + allotmentHarvest[allotmentFieldsData.getAllotmentIndex()]--; + player.startAnimation( + FarmingConstants.SPADE_ANIM); + player.getPacketSender().sendMessage( + "You harvest the crop, and get some vegetables."); + player.getItemAssistant().addItem(allotmentData.getHarvestId(), 1); + player.getPlayerAssistant().addSkillXP(allotmentData.getHarvestXp(), SkillConstants.FARMING.ordinal()); + } + + @Override + public void stop() { + updateAllotmentsStates(); + player.getPlayerAssistant().resetAnimation(); + } + }, 2); + return true; + } + + /* putting compost onto the plant */ + + public boolean putCompost(int objectX, int objectY, final int itemId) { + if (itemId != 6032 && itemId != 6034) { + return false; + } + final AllotmentFieldsData allotmentFieldsData = AllotmentFieldsData + .forIdPosition(objectX, objectY); + if (allotmentFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] != 3 + || allotmentState[allotmentFieldsData.getAllotmentIndex()] == 5) { + player.getPacketSender().sendMessage("This patch doesn't need compost."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(1925, 1); + + player.getPacketSender().sendMessage( + "You pour some " + (itemId == 6034 ? "super" : "") + + "compost on the patch."); + player.startAnimation(FarmingConstants.PUTTING_COMPOST); + player.getPlayerAssistant().addSkillXP(itemId == 6034 ? Compost.SUPER_COMPOST_EXP_USE : Compost.COMPOST_EXP_USE, SkillConstants.FARMING.ordinal()); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[allotmentFieldsData.getAllotmentIndex()] *= itemId == 6032 ? COMPOST_CHANCE + : SUPERCOMPOST_CHANCE; + allotmentState[allotmentFieldsData.getAllotmentIndex()] = 5; + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + return true; + } + + /* inspecting a plant */ + + public boolean inspect(int objectX, int objectY) { + final AllotmentFieldsData allotmentFieldsData = AllotmentFieldsData + .forIdPosition(objectX, objectY); + if (allotmentFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + final InspectData inspectData = InspectData + .forId(allotmentSeeds[allotmentFieldsData.getAllotmentIndex()]); + final AllotmentData allotmentData = AllotmentData + .forId(allotmentSeeds[allotmentFieldsData.getAllotmentIndex()]); + if (allotmentState[allotmentFieldsData.getAllotmentIndex()] == 2) { + player.getDialogueHandler().sendStatement("This plant is diseased. Use a plant cure on it to cure it, ", + "or clear the patch with a spade."); + return true; + } else if (allotmentState[allotmentFieldsData.getAllotmentIndex()] == 3) { + player.getDialogueHandler().sendStatement("This plant is dead. You did not cure it while it was diseased.", + "Clear the patch with a spade."); + return true; + } + if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] == 0) { + player.getDialogueHandler().sendStatement("This is an allotment patch. The soil has not been treated.", + "The patch needs weeding."); + } else if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] == 3) { + player.getDialogueHandler().sendStatement("This is an allotment patch. The soil has not been treated.", + "The patch is empty and weeded."); + } else if (inspectData != null && allotmentData != null) { + player.getPacketSender().sendMessage( + "You bend down and start to inspect the patch..."); + + player.startAnimation(1331); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] - 4 < inspectData + .getMessages().length - 2) { + player.getDialogueHandler().sendStatement(inspectData.getMessages()[allotmentStages[allotmentFieldsData + .getAllotmentIndex()] - 4]); + } else if (allotmentStages[allotmentFieldsData + .getAllotmentIndex()] < allotmentData + .getEndingState() + - allotmentData.getStartingState() + 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 2]); + } else { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 1]); + } + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(1332); + player.stopPlayer(false); + // player.reset(); + } + }, 5); + } + return true; + } + + /* opening the corresponding guide about the patch */ + + public boolean guide(int objectX, int objectY) { + final AllotmentFieldsData allotmentFieldsData = AllotmentFieldsData + .forIdPosition(objectX, objectY); + if (allotmentFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + player.getSkillInterfaces().farmingComplex(1); + player.getSkillInterfaces().selected = 20; + return true; + } + + /* protects the patch with the flowers */ + + public void handleFlowerProtection(int index) { + AllotmentData allotmentData = AllotmentData + .forId(allotmentSeeds[index]); + if (allotmentData == null) { + return; + } + double chance = diseaseChance[index] * allotmentData.getDiseaseChance(); + @SuppressWarnings("unused") + int maxChance = (int) chance * 100; + int indexGiven = 0; + if (!allotmentWatched[index]) {// Misc.random(100) <= maxChance) { + switch (index) { + case 0: + case 1: + indexGiven = 3; + break; + case 2: + case 3: + indexGiven = 2; + break; + case 4: + case 5: + indexGiven = 1; + break; + case 6: + case 7: + indexGiven = 0; + break; + + } + if (player.getFlowers().flowerSeeds[indexGiven] >= 0x21 + && player.getFlowers().flowerSeeds[indexGiven] <= 0x24) { + if (allotmentData.getFlowerProtect() == Flowers.SCARECROW) { + return; + } + } + if (player.getFlowers().flowerState[indexGiven] != 3 + && player.getFlowers().hasFullyGrown[indexGiven] + && player.getFlowers().flowerSeeds[indexGiven] == allotmentData + .getFlowerProtect()) { + player.getFlowers().flowerState[indexGiven] = 3; + player.getFlowers().updateFlowerStates(); + } else { + allotmentState[index] = 2; + } + } + + } + + /* Curing the plant */ + + public boolean curePlant(int objectX, int objectY, int itemId) { + final AllotmentFieldsData allotmentFieldsData = AllotmentFieldsData + .forIdPosition(objectX, objectY); + if (allotmentFieldsData == null || itemId != 6036) { + return false; + } + final AllotmentData allotmentData = AllotmentData + .forId(allotmentSeeds[allotmentFieldsData.getAllotmentIndex()]); + if (allotmentData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (allotmentState[allotmentFieldsData.getAllotmentIndex()] != 2) { + player.getPacketSender().sendMessage("This plant doesn't need to be cured."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(229, 1); + player.startAnimation(FarmingConstants.CURING_ANIM); + player.stopPlayer(true); + allotmentState[allotmentFieldsData.getAllotmentIndex()] = 0; + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender().sendMessage( + "You cure the plant with a plant cure."); + container.stop(); + } + + @Override + public void stop() { + updateAllotmentsStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + + return true; + + } + + /* reseting the patches */ + + private void resetAllotments(int index) { + allotmentSeeds[index] = 0; + allotmentState[index] = 0; + diseaseChance[index] = 1; + allotmentHarvest[index] = 0; + allotmentWatched[index] = false; + hasFullyGrown[index] = false; + } + + /* checking if the patch is raked */ + + public boolean checkIfRaked(int objectX, int objectY) { + final AllotmentFieldsData allotmentFieldsData = AllotmentFieldsData + .forIdPosition(objectX, objectY); + if (allotmentFieldsData == null) + return false; + if (allotmentStages[allotmentFieldsData.getAllotmentIndex()] == 3) + return true; return false; - } } diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Bushes.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Bushes.java new file mode 100644 index 00000000..502cea8c --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Bushes.java @@ -0,0 +1,944 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.rebotted.game.content.skills.farming; + +/** + * + * @author ArrowzFtw + */ + +import java.awt.Point; +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; + +/** + * Created by IntelliJ IDEA. User: vayken Date: 24/02/12 Time: 20:34 To change + * this template use File | Settings | File Templates. + */ +public class Bushes { + + private Player player; + + // set of global constants for Farming + + private static final double COMPOST_CHANCE = 0.9; + private static final double SUPERCOMPOST_CHANCE = 0.7; + private static final double CLEARING_EXPERIENCE = 4; + + public Bushes(Player player) { + this.player = player; + } + + // Farming data + public int[] bushesStages = new int[4]; + public int[] bushesSeeds = new int[4]; + public int[] bushesState = new int[4]; + public long[] bushesTimer = new long[4]; + public double[] diseaseChance = { 1, 1, 1, 1 }; + public boolean[] hasFullyGrown = { false, false, false, false }; + public boolean[] bushesWatched = { false, false, false, false }; + + /* set of the constants for the patch */ + + // states - 2 bits plant - 6 bits + public static final int GROWING = 0x00; + public static final int DISEASED = 0x01; + public static final int DEAD = 0x02; + public static final int CHECK = 0x03; + + public static final int MAIN_BUSHES_CONFIG = 509; + + /* This is the enum holding the seeds info */ + + public enum BushesData { + REDBERRY(5101, 1951, 1, 10, new int[] { 5478, 4 }, 100, 0.20, 11.5, + 4.5, 0x05, 0x0e, 0x09, 0x3a, 64), CADAVABERRY(5102, 753, 1, 22, + new int[] { 5968, 3 }, 140, 0.20, 18, 7, 0x0f, 0x19, 0x14, + 0x3b, 102.5), DWELLBERRY(5103, 2126, 1, 36, + new int[] { 5406, 3 }, 140, 0.20, 31.5, 12, 0x1a, 0x25, 0x20, + 0x3c, 177.5), JANGERBERRY(5104, 247, 1, 48, + new int[] { 5982, 6 }, 160, 0.20, 50.5, 19, 0x26, 0x32, 0x2d, + 0x3d, 284.5), WHITEBERRY(5105, 239, 1, 59, + new int[] { 6004, 8 }, 160, 0.20, 78, 29, 0x33, 0x3f, 0x3a, + 0x3e, 437.5), POISONIVYBERRY(5106, 6018, 1, 70, null, 160, + 0.20, 120, 45, 0xc5, 0xd1, 0xcc, 0x3f, 674); + + private int seedId; + private int harvestId; + private int seedAmount; + private int levelRequired; + private int[] paymentToWatch; + private int growthTime; + private double diseaseChance; + private double plantingXp; + private double harvestXp; + private int startingState; + private int endingState; + private int limitState; + private int checkHealthState; + private double checkHealthExperience; + + private static Map seeds = new HashMap(); + + static { + for (BushesData data : BushesData.values()) { + seeds.put(data.seedId, data); + } + } + + BushesData(int seedId, int harvestId, int seedAmount, + int levelRequired, int[] paymentToWatch, int growthTime, + double diseaseChance, double plantingXp, double harvestXp, + int startingState, int endingState, int limitState, + int checkHealthState, double checkHealthExperience) { + this.seedId = seedId; + this.harvestId = harvestId; + this.seedAmount = seedAmount; + this.levelRequired = levelRequired; + this.paymentToWatch = paymentToWatch; + this.growthTime = growthTime; + this.diseaseChance = diseaseChance; + this.plantingXp = plantingXp; + this.harvestXp = harvestXp; + this.startingState = startingState; + this.endingState = endingState; + this.limitState = limitState; + this.checkHealthState = checkHealthState; + this.checkHealthExperience = checkHealthExperience; + } + + public static BushesData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public int getHarvestId() { + return harvestId; + } + + public int getSeedAmount() { + return seedAmount; + } + + public int getLevelRequired() { + return levelRequired; + } + + public int[] getPaymentToWatch() { + return paymentToWatch; + } + + public int getGrowthTime() { + return growthTime; + } + + public double getDiseaseChance() { + return diseaseChance; + } + + public double getPlantingXp() { + return plantingXp; + } + + public double getHarvestXp() { + return harvestXp; + } + + public int getStartingState() { + return startingState; + } + + public int getEndingState() { + return endingState; + } + + public int getLimitState() { + return limitState; + } + + public int getCheckHealthState() { + return checkHealthState; + } + + public double getCheckHealthXp() { + return checkHealthExperience; + } + } + + /* This is the enum data about the different patches */ + + public enum BushesFieldsData { + ETCETERIA(0, + new Point[] { new Point(2591, 3863), new Point(2592, 3864) }, + 2337), SOUTH_ARDOUGNE(1, new Point[] { new Point(2617, 3225), + new Point(2618, 3226) }, 2338), CHAMPION_GUILD(2, new Point[] { + new Point(3181, 3357), new Point(3182, 3358) }, 2335), RIMMINGTON( + 3, + new Point[] { new Point(2940, 3221), new Point(2941, 3222) }, + 2336); + + private int bushesIndex; + private Point[] bushesPosition; + private int npcId; + + private static Map npcsProtecting = new HashMap(); + + static { + for (BushesFieldsData data : BushesFieldsData.values()) { + npcsProtecting.put(data.npcId, data); + + } + } + + public static BushesFieldsData forId(int npcId) { + return npcsProtecting.get(npcId); + } + + BushesFieldsData(int bushesIndex, Point[] bushesPosition, int npcId) { + this.bushesIndex = bushesIndex; + this.bushesPosition = bushesPosition; + this.npcId = npcId; + } + + public static BushesFieldsData forIdPosition(int x, int y) { + for (BushesFieldsData bushesFieldsData : BushesFieldsData.values()) { + if (FarmingConstants.inRangeArea( + bushesFieldsData.getBushesPosition()[0], + bushesFieldsData.getBushesPosition()[1], x, y)) { + return bushesFieldsData; + } + } + return null; + } + + public int getBushesIndex() { + return bushesIndex; + } + + public Point[] getBushesPosition() { + return bushesPosition; + } + + public int getNpcId() { + return npcId; + } + } + + /* This is the enum that hold the different data for inspecting the plant */ + + public enum InspectData { + + REDBERRY(5101, new String[][] { + { "The Redberry seeds have only just been planted." }, + { "The Redberry bush grows larger." }, + { "The Redberry bush grows larger." }, + { "The Redberry bush grows small, unripe,", "green berries." }, + { "The berries grow larger, and pink." }, + { "The Redberry bush is ready to harvest.", + "The berries on the bush are red." }, }), CADAVABERRY( + 5102, + new String[][] { + { "The Cadavaberry seeds have only just been planted." }, + { "The Cadavaberry bush grows larger." }, + { "The Cadavaberry bush grows larger." }, + { "The Cadavaberry bush grows larger." }, + { "The Cadavaberry bush grows small, unripe,", + "green berries." }, + { "The berries grow larger, and pink." }, + { "The Cadavaberry bush is ready to harvest.", + "The berries on the bush are purple." } }), DWELLBERRY( + 5103, new String[][] { + { "The Dwellbery seeds have only just been planted." }, + { "The Dwellbery bush grows larger." }, + { "The Dwellbery bush grows larger." }, + { "The Dwellbery bush grows larger." }, + { "The Dwellbery bush grows larger." }, + { "The Dwellbery bush grows small, unripe,", + "green berries." }, + { "The berries grow larger, and light blue." }, + { "The Dwellbery bush is ready to harvest.", + "The berries on the bush are blue." }, }), JANGERBERRY( + 5104, + new String[][] { + { "The Jangerberry seeds have only just been planted." }, + { "The Jangerberry bush grows larger." }, + { "The Jangerberry bush grows larger." }, + { "The Jangerberry bush grows larger." }, + { "The Jangerberry bush grows larger." }, + { "The Jangerberry bush grows small, unripe,", + "green berries." }, + { "The berries grow larger." }, + { "The berries grow larger, and light green." }, + { "The Jangerberry bush is ready to harvest.", + "The berries on the bush are green." } }), WHITEBERRY( + 5105, + new String[][] { + { "The Whiteberry seeds have only just been planted." }, + { "The Whiteberry bush grows larger." }, + { "The Whiteberry bush grows larger." }, + { "The Whiteberry bush grows larger." }, + { "The Whiteberry bush grows larger." }, + { "The Whiteberry bush grows larger." }, + { "The Whiteberry bush grows small, unripe,", + "green berries." }, + { "The berries grow larger." }, + { "The Whiteberry bush is ready to harvest.", + "The berries on the bush are white." }, }), POISONIVYBERRY( + 5106, + new String[][] { + { "The Poison ivy seeds have only just been planted." }, + { "The Poison ivy bush grows larger." }, + { "The Poison ivy bush grows larger." }, + { "The Poison ivy bush grows larger." }, + { "The Poison ivy bush grows larger." }, + { "The Poison ivy bush grows small, unripe,", + "green berries." }, + { "The berries grow larger." }, + { "The berries grow larger, and light green." }, + { "The Poison ivy bush is ready to harvest.", + "The berries on the bush are pale yellow." } }); + private int seedId; + private String[][] messages; + + private static Map seeds = new HashMap(); + + static { + for (InspectData data : InspectData.values()) { + seeds.put(data.seedId, data); + } + } + + InspectData(int seedId, String[][] messages) { + this.seedId = seedId; + this.messages = messages; + } + + public static InspectData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public String[][] getMessages() { + return messages; + } + } + + /* update all the patch states */ + + public void updateBushesStates() { + // etceteria - south ardougne - champion guild - rimmington + int[] configValues = new int[bushesStages.length]; + + int configValue; + for (int i = 0; i < bushesStages.length; i++) { + configValues[i] = getConfigValue(bushesStages[i], bushesSeeds[i], + bushesState[i], i); + } + + configValue = (configValues[0] << 16) + (configValues[1] << 8 << 16) + + configValues[2] + (configValues[3] << 8); + player.getPacketSender().sendConfig(MAIN_BUSHES_CONFIG, configValue); + } + + /* getting the different config values */ + + public int getConfigValue(int bushesStage, int seedId, int plantState, + int index) { + BushesData bushesData = BushesData.forId(seedId); + switch (bushesStage) { + case 0:// weed + return (GROWING << 6) + 0x00; + case 1:// weed cleared + return (GROWING << 6) + 0x01; + case 2: + return (GROWING << 6) + 0x02; + case 3: + return (GROWING << 6) + 0x03; + } + if (bushesData == null) { + return -1; + } + if (bushesStage > bushesData.getEndingState() + - bushesData.getStartingState() - 1) { + hasFullyGrown[index] = true; + } + if (getPlantState(plantState) == 3) + return (getPlantState(plantState) << 6) + + bushesData.getCheckHealthState(); + if (seedId == 5106) { + if (getPlantState(plantState) == 1) { + return bushesData.getStartingState() + bushesStage - 4 + 12; + } else if (getPlantState(plantState) == 2) { + return bushesData.getStartingState() + bushesStage - 4 + 20; + } + } + return (getPlantState(plantState) << 6) + bushesData.getStartingState() + + bushesStage - 4 + (getPlantState(plantState) == 2 ? -1 : 0); + } + + /* getting the plant states */ + + public int getPlantState(int plantState) { + switch (plantState) { + case 0: + return GROWING; + case 1: + return DISEASED; + case 2: + return DEAD; + case 3: + return CHECK; + } + return -1; + } + + /* calculating the disease chance and making the plant grow */ + + public void doCalculations() { + for (int i = 0; i < bushesSeeds.length; i++) { + if (bushesStages[i] > 0 && bushesStages[i] <= 3 + && GameEngine.getMinutesCounter() - bushesTimer[i] >= 5) { + bushesStages[i]--; + bushesTimer[i] = GameEngine.getMinutesCounter(); + updateBushesStates(); + continue; + } + BushesData bushesData = BushesData.forId(bushesSeeds[i]); + if (bushesData == null) { + continue; + } + + long difference = GameEngine.getMinutesCounter() - bushesTimer[i]; + long growth = bushesData.getGrowthTime(); + int nbStates = bushesData.getEndingState() + - bushesData.getStartingState(); + int state = (int) (difference * nbStates / growth); + if (bushesTimer[i] == 0 || bushesState[i] == 2 + || bushesState[i] == 3 || (state > nbStates)) { + continue; + } + if (4 + state != bushesStages[i]) { + if (bushesStages[i] == bushesData.getEndingState() + - bushesData.getStartingState() - 1) { + bushesStages[i] = bushesData.getEndingState() + - bushesData.getStartingState() + 4; + bushesState[i] = 3; + updateBushesStates(); + return; + } + bushesStages[i] = 4 + state; + if (bushesStages[i] <= 4 + state) + for (int j = bushesStages[i]; j <= 4 + state; j++) + doStateCalculation(i); + updateBushesStates(); + } + } + } + + public void modifyStage(int i) { + BushesData bushesData = BushesData.forId(bushesSeeds[i]); + if (bushesData == null) + return; + long difference = GameEngine.getMinutesCounter() - bushesTimer[i]; + long growth = bushesData.getGrowthTime(); + int nbStates = bushesData.getEndingState() + - bushesData.getStartingState(); + int state = (int) (difference * nbStates / growth); + bushesStages[i] = 4 + state; + updateBushesStates(); + + } + + /* calculations about the diseasing chance */ + + public void doStateCalculation(int index) { + if (bushesState[index] == 2) { + return; + } + // if the patch is diseased, it dies, if its watched by a farmer, it + // goes back to normal + if (bushesState[index] == 1) { + if (bushesWatched[index]) { + bushesState[index] = 0; + BushesData bushesData = BushesData.forId(bushesSeeds[index]); + if (bushesData == null) + return; + System.out.println(bushesSeeds[index]); + int difference = bushesData.getEndingState() + - bushesData.getStartingState(); + int growth = bushesData.getGrowthTime(); + bushesTimer[index] += (growth / difference); + modifyStage(index); + } else { + bushesState[index] = 2; + } + } + + if (bushesState[index] == 5 && bushesStages[index] != 2) { + bushesState[index] = 0; + } + + if (bushesState[index] == 0 && bushesStages[index] >= 5 + && !hasFullyGrown[index]) { + BushesData bushesData = BushesData.forId(bushesSeeds[index]); + if (bushesData == null) { + return; + } + + double chance = diseaseChance[index] + * bushesData.getDiseaseChance(); + int maxChance = (int) chance * 100; + if (Misc.random(100) <= maxChance) { + bushesState[index] = 1; + } + } + } + + /* clearing the patch with a rake of a spade */ + + public boolean clearPatch(int objectX, int objectY, int itemId) { + final BushesFieldsData bushesFieldsData = BushesFieldsData + .forIdPosition(objectX, objectY); + int finalAnimation; + int finalDelay; + if (bushesFieldsData == null + || (itemId != FarmingConstants.RAKE && itemId != FarmingConstants.SPADE)) { + return false; + } + if (bushesStages[bushesFieldsData.getBushesIndex()] == 3) { + return true; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (bushesStages[bushesFieldsData.getBushesIndex()] <= 3) { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a rake to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.RAKING_ANIM; + finalDelay = 5; + } + } else { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement("You need a spade to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.SPADE_ANIM; + finalDelay = 3; + } + } + final int animation = finalAnimation; + player.stopPlayer(true); + player.startAnimation(animation); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.startAnimation(animation); + if (bushesStages[bushesFieldsData.getBushesIndex()] <= 2) { + bushesStages[bushesFieldsData.getBushesIndex()]++; + player.getItemAssistant().addItem(6055, 1); + } else { + bushesStages[bushesFieldsData.getBushesIndex()] = 3; + container.stop(); + } + player.getPlayerAssistant().addSkillXP(CLEARING_EXPERIENCE, SkillConstants.FARMING.ordinal()); + bushesTimer[bushesFieldsData.getBushesIndex()] = GameEngine + .getMinutesCounter(); + updateBushesStates(); + if (bushesStages[bushesFieldsData.getBushesIndex()] == 3) { + container.stop(); + return; + } + } + + @Override + public void stop() { + resetBushes(bushesFieldsData.getBushesIndex()); + player.getPacketSender().sendMessage("You clear the patch."); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, finalDelay); + return true; + + } + + /* planting the seeds */ + + public boolean plantSeed(int objectX, int objectY, final int seedId) { + final BushesFieldsData bushesFieldsData = BushesFieldsData + .forIdPosition(objectX, objectY); + final BushesData bushesData = BushesData.forId(seedId); + if (bushesFieldsData == null || bushesData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (bushesStages[bushesFieldsData.getBushesIndex()] != 3) { + player.getPacketSender().sendMessage("You can't plant a seed here."); + return false; + } + if (bushesData.getLevelRequired() > player.playerLevel[SkillConstants.FARMING.ordinal()]) { + player.getDialogueHandler().sendStatement("You need a farming level of " + + bushesData.getLevelRequired() + + " to plant this seed."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SEED_DIBBER)) { + player.getDialogueHandler().sendStatement( + "You need a seed dibber to plant seed here."); + return true; + } + if (player.getItemAssistant().getItemAmount(bushesData.getSeedId()) < bushesData + .getSeedAmount()) { + player.getDialogueHandler().sendStatement("You need atleast " + + bushesData.getSeedAmount() + " seeds to plant here."); + return true; + } + player.startAnimation(FarmingConstants.SEED_DIBBING); + bushesStages[bushesFieldsData.getBushesIndex()] = 4; + player.getItemAssistant().deleteItem(seedId, bushesData.getSeedAmount()); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + bushesState[bushesFieldsData.getBushesIndex()] = 0; + bushesSeeds[bushesFieldsData.getBushesIndex()] = seedId; + bushesTimer[bushesFieldsData.getBushesIndex()] = GameEngine + .getMinutesCounter(); + + player.getPlayerAssistant().addSkillXP(bushesData.getPlantingXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateBushesStates(); + player.stopPlayer(false); + } + }, 3); + return true; + } + + @SuppressWarnings("unused") + private void displayAll() { + for (int i = 0; i < bushesStages.length; i++) { + System.out.println("index : " + i); + System.out.println("state : " + bushesState[i]); + System.out.println("seeds : " + bushesSeeds[i]); + System.out.println("level : " + bushesStages[i]); + System.out.println("timer : " + bushesTimer[i]); + System.out.println("disease chance : " + diseaseChance[i]); + System.out + .println("-----------------------------------------------------------------"); + } + } + + /* harvesting the plant resulted */ + + public boolean harvestOrCheckHealth(int objectX, int objectY) { + final BushesFieldsData bushesFieldsData = BushesFieldsData + .forIdPosition(objectX, objectY); + if (bushesFieldsData == null) { + return false; + } + final BushesData bushesData = BushesData + .forId(bushesSeeds[bushesFieldsData.getBushesIndex()]); + if (bushesData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (player.getItemAssistant().freeSlots() <= 0) { + player.getPacketSender().sendMessage("Not enough space in your inventory."); + return true; + } + player.startAnimation(832); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (player.getItemAssistant().freeSlots() <= 0) { + container.stop(); + return; + } + + if (bushesState[bushesFieldsData.getBushesIndex()] == 3) { + player.getPacketSender() + .sendMessage( + "You examine the bush for signs of disease and find that it's in perfect health."); + player.getPlayerAssistant().addSkillXP(bushesData.getCheckHealthXp(), SkillConstants.FARMING.ordinal()); + bushesState[bushesFieldsData.getBushesIndex()] = 0; + hasFullyGrown[bushesFieldsData.getBushesIndex()] = false; + bushesTimer[bushesFieldsData.getBushesIndex()] = GameEngine + .getMinutesCounter() - bushesData.getGrowthTime(); + // bushesStages[bushesFieldsData.getBushesIndex()] -= 2; + modifyStage(bushesFieldsData.getBushesIndex()); + container.stop(); + return; + } + player.getPacketSender().sendMessage( + "You harvest the crop, and pick some berries."); + player.getItemAssistant().addItem(bushesData.getHarvestId(), 1); + player.getPlayerAssistant().addSkillXP(bushesData.getHarvestXp(), SkillConstants.FARMING.ordinal()); + bushesTimer[bushesFieldsData.getBushesIndex()] = GameEngine + .getMinutesCounter(); + int difference = bushesData.getEndingState() + - bushesData.getStartingState(); + int growth = bushesData.getGrowthTime(); + lowerStage( + bushesFieldsData.getBushesIndex(), + growth + - (growth / difference) + * (difference + 5 - bushesStages[bushesFieldsData + .getBushesIndex()])); + modifyStage(bushesFieldsData.getBushesIndex()); + container.stop(); + } + + @Override + public void stop() { + player.getPlayerAssistant().resetAnimation(); + } + }, 2); + return true; + } + + /* lowering the stage */ + + public void lowerStage(int index, int timer) { + hasFullyGrown[index] = false; + bushesTimer[index] -= timer; + } + + /* putting compost onto the plant */ + + public boolean putCompost(int objectX, int objectY, final int itemId) { + if (itemId != 6032 && itemId != 6034) { + return false; + } + final BushesFieldsData bushesFieldsData = BushesFieldsData + .forIdPosition(objectX, objectY); + if (bushesFieldsData == null) { + return false; + } + + if (bushesStages[bushesFieldsData.getBushesIndex()] != 3 + || bushesState[bushesFieldsData.getBushesIndex()] == 5) { + player.getPacketSender().sendMessage("This patch doesn't need compost."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(1925, 1); + + player.getPacketSender().sendMessage( + "You pour some " + (itemId == 6034 ? "super" : "") + + "compost on the patch."); + player.startAnimation(FarmingConstants.PUTTING_COMPOST); + player.getPlayerAssistant().addSkillXP(itemId == 6034 ? Compost.SUPER_COMPOST_EXP_USE + : Compost.COMPOST_EXP_USE, SkillConstants.FARMING.ordinal()); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[bushesFieldsData.getBushesIndex()] *= itemId == 6032 ? COMPOST_CHANCE + : SUPERCOMPOST_CHANCE; + bushesState[bushesFieldsData.getBushesIndex()] = 5; + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + return true; + } + + /* inspecting a plant */ + + public boolean inspect(int objectX, int objectY) { + final BushesFieldsData bushesFieldsData = BushesFieldsData + .forIdPosition(objectX, objectY); + if (bushesFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + final InspectData inspectData = InspectData + .forId(bushesSeeds[bushesFieldsData.getBushesIndex()]); + final BushesData bushesData = BushesData + .forId(bushesSeeds[bushesFieldsData.getBushesIndex()]); + if (bushesState[bushesFieldsData.getBushesIndex()] == 1) { + player.getDialogueHandler().sendStatement("This plant is diseased. Use a plant cure on it to cure it, ", + "or clear the patch with a spade."); + return true; + } else if (bushesState[bushesFieldsData.getBushesIndex()] == 2) { + player.getDialogueHandler().sendStatement("This plant is dead. You did not cure it while it was diseased.", + "Clear the patch with a spade."); + return true; + } else if (bushesState[bushesFieldsData.getBushesIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This plant has fully grown. You can check it's health", + "to gain some farming experiences."); + return true; + } + if (bushesStages[bushesFieldsData.getBushesIndex()] == 0) { + player.getDialogueHandler().sendStatement( + "This is a bush patch. The soil has not been treated.", + "The patch needs weeding."); + } else if (bushesStages[bushesFieldsData.getBushesIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This is a bush patch. The soil has not been treated.", + "The patch is empty and weeded."); + } else if (inspectData != null && bushesData != null) { + player.getPacketSender().sendMessage( + "You bend down and start to inspect the patch..."); + + player.startAnimation(1331); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (bushesStages[bushesFieldsData.getBushesIndex()] - 4 < inspectData + .getMessages().length - 2) { + player.getDialogueHandler().sendStatement( inspectData + .getMessages()[bushesStages[bushesFieldsData + .getBushesIndex()] - 4]); + } else if (bushesStages[bushesFieldsData.getBushesIndex()] < bushesData + .getEndingState() + - bushesData.getStartingState() + + 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 2]); + } else { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 1]); + } + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(1332); + player.stopPlayer(false); + // player.reset(); + } + }, 5); + } + return true; + } + + /* opening the corresponding guide about the patch */ + + public boolean guide(int objectX, int objectY) { + final BushesFieldsData bushesFieldsData = BushesFieldsData + .forIdPosition(objectX, objectY); + if (bushesFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + player.getSkillInterfaces().farmingComplex(5); + player.getSkillInterfaces().selected = 20; + return true; + } + + /* Curing the plant */ + + public boolean curePlant(int objectX, int objectY, int itemId) { + final BushesFieldsData bushesFieldsData = BushesFieldsData + .forIdPosition(objectX, objectY); + if (bushesFieldsData == null || itemId != 6036) { + return false; + } + final BushesData bushesData = BushesData + .forId(bushesSeeds[bushesFieldsData.getBushesIndex()]); + if (bushesData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (bushesState[bushesFieldsData.getBushesIndex()] != 1) { + player.getPacketSender().sendMessage("This plant doesn't need to be cured."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(229, 1); + player.startAnimation(FarmingConstants.CURING_ANIM); + player.stopPlayer(true); + bushesState[bushesFieldsData.getBushesIndex()] = 0; + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender().sendMessage( + "You cure the plant with a plant cure."); + container.stop(); + } + + @Override + public void stop() { + updateBushesStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + + return true; + + } + + private void resetBushes(int index) { + bushesSeeds[index] = 0; + bushesState[index] = 0; + diseaseChance[index] = 1; + hasFullyGrown[index] = false; + bushesWatched[index] = false; + } + + /* checking if the patch is raked */ + + public boolean checkIfRaked(int objectX, int objectY) { + final BushesFieldsData bushesFieldData = BushesFieldsData + .forIdPosition(objectX, objectY); + if (bushesFieldData == null) + return false; + if (bushesStages[bushesFieldData.getBushesIndex()] == 3) + return true; + return false; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/ChopTree.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/ChopTree.java new file mode 100644 index 00000000..198af059 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/ChopTree.java @@ -0,0 +1,243 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.rebotted.game.content.skills.farming; + +import com.rebotted.GameConstants; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; + +public class ChopTree { + + private static final Axe[] axes = new Axe[8]; + private static final Tree[] trees = new Tree[11]; + + public static final int[] COMMON_SEEDS = { 5312, 5283, 5284, 5285, 5286, + 5313 }; + public static final int[] UNCOMMON_SEEDS = { 5314, 5288, 5287, 5315, 5289 }; + public static final int[] RARE_SEEDS = { 5316, 5290 }; + public static final int[] VERY_RARE_SEEDS = { 5317 }; + + public static final int[] COMMON_RING = { 1635, 1637 }; + public static final int[] UNCOMMON_RING = { 1639 }; + public static final int[] RARE_RING = { 1641 }; + public static final int[] VERY_RARE_RING = { 1643 }; + + static { + // Initialise axes + axes[0] = new Axe(1351, 1, 508, 879, 0); + axes[1] = new Axe(1349, 1, 510, 877, 1); + axes[2] = new Axe(1353, 6, 512, 875, 2); + axes[3] = new Axe(1361, 6, 514, 873, 3); + axes[4] = new Axe(1355, 21, 516, 871, 4); + axes[5] = new Axe(1357, 31, 518, 869, 5); + axes[6] = new Axe(1359, 41, 520, 867, 6); + axes[7] = new Axe(6739, 61, 6743, 2846, 7); + // Initialise trees + trees[0] = new Tree(new int[] { 2023 }, 1, 25, 2862, 3371, 75, 100); + trees[1] = new Tree(new int[] { 1276, 1277, 1278, 1279, 1280, 1282, + 1283, 1284, 1285, 1286, 1289, 1290, 1291, 1315, 1316, 1318, + 1319, 1330, 1331, 1332, 1333, 1365, 1383, 1384, 2409, 3033, + 3034, 3035, 3036, 3881, 3882, 3883, 5902, 5903, 5904 }, 1, 25, + 1511, 1342, 75, 100); + trees[2] = new Tree(new int[] { 1281, 2037 }, 15, 37.5, 1521, 1356, 14, + 25); + trees[3] = new Tree(new int[] { 1308, 5551, 5552, 5553 }, 30, 67.5, + 1519, 7399, 14, 5); + trees[4] = new Tree(new int[] { 9036 }, 35, 85, 6333, 9037, 14, 20); + trees[5] = new Tree(new int[] { 1307, 4677 }, 45, 100, 1517, 1343, 59, + 15); + trees[6] = new Tree(new int[] { 2289, 4060 }, 45, 83, 3239, 2310, 59, + 15); + trees[7] = new Tree(new int[] { 9034 }, 50, 125, 6332, 9035, 80, 10); + trees[8] = new Tree(new int[] { 1309 }, 60, 175, 1515, 7402, 100, 5); + trees[9] = new Tree(new int[] { 1306 }, 75, 250, 1513, 7401, 200, 3); + trees[10] = new Tree(new int[] { 1292 }, 36, 0, 771, 1513, 59, 100); + + } + + public static class Axe { + + private int id; + private int level; + private int head; + private int animation; + private int bonus; + + public Axe(int id, int level, int head, int animation, int bonus) { + this.id = id; + this.level = level; + this.head = head; + this.animation = animation; + this.bonus = bonus; + } + + public int getId() { + return id; + } + + public int getLevel() { + return level; + } + + public int getHead() { + return head; + } + + public int getAnimation() { + return animation; + } + + public int getBonus() { + return bonus; + } + + } + + public static class Tree { + private int[] id; + private int level; + private double xp; + private int log; + private int stump; + private int respawnTime; + private int decayChance; + + public Tree(int[] id, int level, double xp, int log, int stump, + int respawnTime, int decayChance) { + this.id = id; + this.level = level; + this.xp = xp; + this.log = log; + this.stump = stump; + this.respawnTime = respawnTime; + this.decayChance = decayChance; + } + + public int[] getId() { + return id; + } + + public int getLevel() { + return level; + } + + public double getXP() { + return xp; + } + + public int getLog() { + return log; + } + + public int getStump() { + return stump; + } + + public int getRespawnTime() { + return respawnTime; + } + + public int getDecayChance() { + return decayChance; + } + } + + public static boolean handleNest(Player player, int itemId) { + int[] commonItems, uncommonItems, rareItems, veryRareItems; + switch (itemId) { + case 5070: + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(5075, 1); + player.getItemAssistant().addItem(5076, 1); + return true; + case 5071: + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(5075, 1); + player.getItemAssistant().addItem(5078, 1); + return true; + case 5072: + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(5075, 1); + player.getItemAssistant().addItem(5077, 1); + return true; + case 5073: + commonItems = COMMON_SEEDS; + uncommonItems = UNCOMMON_SEEDS; + rareItems = RARE_SEEDS; + veryRareItems = VERY_RARE_SEEDS; + break; + case 5074: + commonItems = COMMON_RING; + uncommonItems = UNCOMMON_RING; + rareItems = RARE_RING; + veryRareItems = VERY_RARE_RING; + break; + default: + return false; + } + int randomNumber = Misc.random(100), finalItem; + if (randomNumber <= 60) + finalItem = commonItems[Misc.random(commonItems.length - 1)]; + else if (randomNumber <= 80) + finalItem = uncommonItems[Misc.random(uncommonItems.length - 1)]; + else if (randomNumber <= 95) + finalItem = rareItems[Misc.random(rareItems.length - 1)]; + else + finalItem = veryRareItems[Misc.random(veryRareItems.length - 1)]; + + player.getPacketSender().sendMessage( + "You search the nest...and find something in it!"); + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(5075, 1); + player.getItemAssistant().addItem(finalItem, 1); + return true; + } + + public static Axe getAxe(Player player) { + final int axeIndex = getAxeIndex(player); + if (axeIndex == -1) { + return null; + } + return axes[axeIndex]; + } + + public static Tree getTree(int objectId) { + final int treeIndex = getTreeIndex(objectId); + if (treeIndex == -1) { + return null; + } + return trees[treeIndex]; + } + + public static int getAxeIndex(Player player) { + for (int i = 0; i < axes.length; i++) { + if (player.playerEquipment[GameConstants.WEAPON] == (axes[i].getId())) { + return i; + } + } + for (int i = axes.length - 1; i >= 0; i--) { + if (player.getItemAssistant().playerHasItem(axes[i].getId())) { + if (player.playerLevel[SkillConstants.WOODCUTTING.ordinal()] >= axes[i].getLevel()) { + return i; + } + } + } + return -1; + } + + public static int getTreeIndex(final int objectId) { + for (int i = 0; i < trees.length; i++) { + int[] ids = trees[i].getId(); + for (int id : ids) { + if (objectId == id) { + return i; + } + } + } + return -1; + } + +} \ No newline at end of file diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Compost.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Compost.java new file mode 100644 index 00000000..daafb931 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Compost.java @@ -0,0 +1,545 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.rebotted.game.content.skills.farming; + +/** + * + * @author ArrowzFtw + */ + +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.players.Player; + +/** + * Created by IntelliJ IDEA. User: vayken Date: 22/02/12 Time: 15:43 To change + * this template use File | Settings | File Templates. + */ +public class Compost { + + private Player player; + + public Compost(Player player) { + this.player = player; + } + + public int[] compostBins = new int[4]; + public long[] compostBinsTimer = new long[4]; + public int[] organicItemAdded = new int[4]; + public int tempCompostState; + + /* setting up the experiences constants */ + + public static final double COMPOST_EXP_RETRIEVE = 4.5; + public static final double SUPER_COMPOST_EXP_RETRIEVE = 8.5; + public static final double COMPOST_EXP_USE = 18; + public static final double SUPER_COMPOST_EXP_USE = 26; + + public static final double ROTTEN_TOMATOES_EXP_RETRIEVE = 8.5; + + /* these are the constants related to compost making */ + + public static final int COMPOST = 6032; + + public static final int SUPER_COMPOST = 6034; + + public static final int ROTTE_TOMATO = 2518; + + public static final int TOMATO = 1982; + + public static final int FIRST_TYPE_COMPOST_BIN = 7808; + + public static final int SECOND_TYPE_COMPOST_BIN = 7818; + + public static final int[] COMPOST_ORGANIC = { 6055, 1942, 1957, 1965, 5986, + 5504, 5982, 249, 251, 253, 255, 257, 2998, 259, 261, 263, 3000, + 265, 2481, 267, 269, 1951, 753, 2126, 247, 239, 6018 }; + + public static final int[] SUPER_COMPOST_ORGANIC = { 2114, 5978, 5980, 5982, + 6004, 247, 6469 }; + + /* this is the enum that stores the different locations of the compost bins */ + + public enum CompostBinLocations { + NORTH_ARDOUGNE(0, FIRST_TYPE_COMPOST_BIN, 3, 2661, 3375), PHASMATYS(1, + SECOND_TYPE_COMPOST_BIN, 1, 3610, 3522), FALADOR(2, + FIRST_TYPE_COMPOST_BIN, 4, 3056, 3312), CATHERBY(3, + FIRST_TYPE_COMPOST_BIN, 3, 2804, 3464); + + private int compostIndex; + private int binObjectId; + private int objectFace; + private int x, y, z; + private static Map bins = new HashMap(); + + static { + for (CompostBinLocations data : CompostBinLocations.values()) { + bins.put(data.compostIndex, data); + } + } + + CompostBinLocations(int compostIndex, int binObjectId, int objectFace, + int x, int y) { + this.compostIndex = compostIndex; + this.binObjectId = binObjectId; + this.objectFace = objectFace; + this.x = x; + this.y = y; + } + + public static CompostBinLocations forId(int index) { + return bins.get(index); + } + + public static CompostBinLocations forPosition(int x, int y) { + for (CompostBinLocations compostBinLocations : CompostBinLocations + .values()) { + if (compostBinLocations.x == x && compostBinLocations.y == y) { + return compostBinLocations; + } + } + return null; + } + + public int getCompostIndex() { + return compostIndex; + } + + public int getBinObjectId() { + return binObjectId; + } + + public int getObjectFace() { + return objectFace; + } + } + + /* this is the enum that stores the different compost bins stages */ + + public enum CompostBinStages { + FIRST_TYPE(7808, 7813, 7809, 7810, 7811, 7812, 7814, 7815, 7816, 7817, + 7828, 7829, 7830, 7831), SECOND_TYPE(7818, 7823, 7819, 7820, + 7821, 7822, 7824, 7825, 7826, 7827, 7832, 7833, 7834, 7835); + private int binEmpty; + private int closedBin; + private int binWithCompostable; + private int binFullOfCompostable; + private int binWithSuperCompostable; + private int binFullOFSuperCompostable; + private int binWithCompost; + private int binFullOfCompost; + private int binWithSuperCompost; + private int binFullOfSuperCompost; + private int binWithTomatoes; + private int binFullOfTomatoes; + private int binWithRottenTomatoes; + private int binFullOfRottenTomatoes; + + private static Map bins = new HashMap(); + + static { + for (CompostBinStages data : CompostBinStages.values()) { + bins.put(data.binEmpty, data); + } + } + + CompostBinStages(int binEmpty, int closedBin, int binWithCompostable, + int binFullOfCompostable, int binWithSuperCompostable, + int binFullOFSuperCompostable, int binWithCompost, + int binFullOfCompost, int binWithSuperCompost, + int binFullOfSuperCompost, int binWithTomatoes, + int binFullOfTomatoes, int binWithRottenTomatoes, + int binFullOfRottenTomatoes) { + this.binEmpty = binEmpty; + this.closedBin = closedBin; + this.binWithCompostable = binWithCompostable; + this.binFullOfCompostable = binFullOfCompostable; + this.binWithSuperCompostable = binWithSuperCompostable; + this.binFullOFSuperCompostable = binFullOFSuperCompostable; + this.binWithCompost = binWithCompost; + this.binFullOfCompost = binFullOfCompost; + this.binWithSuperCompost = binWithSuperCompost; + this.binFullOfSuperCompost = binFullOfSuperCompost; + this.binWithTomatoes = binWithTomatoes; + this.binFullOfTomatoes = binFullOfTomatoes; + this.binWithRottenTomatoes = binWithRottenTomatoes; + this.binFullOfRottenTomatoes = binFullOfRottenTomatoes; + } + + public static CompostBinStages forId(int binId) { + return bins.get(binId); + } + + public int getBinEmpty() { + return binEmpty; + } + + public int getClosedBin() { + return closedBin; + } + + public int getBinWithCompostable() { + return binWithCompostable; + } + + public int getBinFullOfCompostable() { + return binFullOfCompostable; + } + + public int getBinWithSuperCompostable() { + return binWithSuperCompostable; + } + + public int getBinFullOFSuperCompostable() { + return binFullOFSuperCompostable; + } + + public int getBinWithCompost() { + return binWithCompost; + } + + public int getBinFullOfCompost() { + return binFullOfCompost; + } + + public int getBinWithSuperCompost() { + return binWithSuperCompost; + } + + public int getBinFullOfSuperCompost() { + return binFullOfSuperCompost; + } + + public int getBinWithTomatoes() { + return binWithTomatoes; + } + + public int getBinFullOfTomatoes() { + return binFullOfTomatoes; + } + + public int getBinWithRottenTomatoes() { + return binWithRottenTomatoes; + } + + public int getBinFullOfRottenTomatoes() { + return binFullOfRottenTomatoes; + } + } + + /* handle compost bin updating */ + private void updateCompostBin(int index) { + CompostBinStages compostBinStages = CompostBinStages + .forId(CompostBinLocations.forId(index).getBinObjectId()); + + if (compostBinStages == null) { + return; + } + int x = CompostBinLocations.forId(index).x; + int y = CompostBinLocations.forId(index).y; + int z = CompostBinLocations.forId(index).z; + int finalObject; + + // handling the different ways to fill a compost bin + if (compostBins[index] > 0) { + if (compostBins[index] % 17 == 0) { + finalObject = compostBinStages.getBinWithSuperCompostable(); + } else if (compostBins[index] % 77 == 0) { + finalObject = compostBinStages.getBinWithTomatoes(); + } else { + finalObject = compostBinStages.getBinWithCompostable(); + } + } else { + finalObject = compostBinStages.getBinEmpty(); + } + + // handling the different ways to complete a compost bin + if (compostBins[index] == 255) { + finalObject = compostBinStages.getBinFullOFSuperCompostable(); + tempCompostState = 2; + } else if (compostBins[index] == 1155) { + finalObject = compostBinStages.getBinFullOfTomatoes(); + tempCompostState = 3; + } else if (organicItemAdded[index] == 15) { + finalObject = compostBinStages.getBinFullOfCompostable(); + tempCompostState = 1; + } + // handling the closed state of the compost bin + switch (compostBins[index]) { + + case 100: + case 200: + case 300: + finalObject = compostBinStages.getClosedBin(); + break; + + // handling the rotted state of the compost in the bin + case 150: + finalObject = compostBinStages.getBinFullOfCompost(); + break; + case 250: + finalObject = compostBinStages.getBinFullOfSuperCompost(); + break; + case 350: + finalObject = compostBinStages.getBinFullOfRottenTomatoes(); + break; + + } + + // handle the compost bin state when the player retrieve the compost + if (compostBins[index] == 150 && organicItemAdded[index] < 15) { + finalObject = compostBinStages.getBinWithCompost(); + } else if (compostBins[index] == 250 && organicItemAdded[index] < 15) { + finalObject = compostBinStages.getBinWithSuperCompost(); + } + if (compostBins[index] == 350 && organicItemAdded[index] < 15) { + finalObject = compostBinStages.getBinWithRottenTomatoes(); + } + + player.getPacketSender().object(finalObject, x, y, z, + CompostBinLocations.forId(index).getObjectFace(), 10); + } + + /* handle what happens when the player close the compost bin */ + public void closeCompostBin(final int index) { + compostBins[index] = tempCompostState * 100; + compostBinsTimer[index] = GameEngine.getMinutesCounter(); + + player.startAnimation(835, 0); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender() + .sendMessage( + "You close the compost bin, and its content start to rot."); + updateCompostBin(index); + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + } + }, 2); + } + + /* handle what happens when the player opens the compost bin */ + public void openCompostBin(final int index) { + // check if the time elapsed is enough to rot the compost + int timerRequired; + timerRequired = compostBins[index] == 200 ? 90 : 45; + if (GameEngine.getMinutesCounter() - compostBinsTimer[index] >= timerRequired) { + compostBins[index] += 50; + player.startAnimation(834, 0); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + updateCompostBin(index); + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + } + }, 2); + } else { + player.getPacketSender() + .sendMessage( + "The compost bin is still rotting. I should wait until it is complete."); + } + } + + /* handle compost bin filling */ + @SuppressWarnings("unused") + public void fillCompostBin(int x, int y, final int organicItemUsed) { + final CompostBinLocations compostBinLocations = CompostBinLocations + .forPosition(x, y); + final int index = compostBinLocations.getCompostIndex(); + if (compostBinLocations == null) { + return; + } + + int incrementFactor = 0; + // setting up the different increments. + for (int normalCompost : COMPOST_ORGANIC) { + if (organicItemUsed == normalCompost) { + incrementFactor = 2; + } + } + + for (int superCompost : SUPER_COMPOST_ORGANIC) { + if (organicItemUsed == superCompost) { + incrementFactor = 17; + } + } + + if (organicItemUsed == TOMATO) { + if (compostBins[index] % 77 == 0) { + incrementFactor = 77; + } else { + incrementFactor = 2; + } + } + + // checking if the item used was an organic item. + if (incrementFactor == 0) { + player.getPacketSender() + .sendMessage( + "You need to put organic items into the compost bin in order to make compost."); + return; + } + final int factor = incrementFactor; + // launching the main event for filling the compost bin. + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (!player.getItemAssistant().playerHasItem(organicItemUsed) + || organicItemAdded[index] == 15) { + container.stop(); + return; + } + organicItemAdded[index]++; + player.startAnimation(832, 0); + player.getItemAssistant().deleteItem(organicItemUsed, 1); + compostBins[index] += factor; + updateCompostBin(index); + + } + + @Override + public void stop() { + player.getPlayerAssistant().resetAnimation(); + } + }, 2); + } + + // handle what happens when the player retrieve the compost + public void retrieveCompost(final int index) { + + final int finalItem = compostBins[index] == 150 ? COMPOST : compostBins[index] == 250 ? SUPER_COMPOST : ROTTE_TOMATO; + + player.startAnimation(832, 0); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (!player.getItemAssistant().playerHasItem(1925) + && compostBins[index] != 350 + || organicItemAdded[index] == 0) { + container.stop(); + return; + } + player.getPlayerAssistant().addSkillXP(finalItem == COMPOST ? COMPOST_EXP_RETRIEVE + : finalItem == SUPER_COMPOST ? SUPER_COMPOST_EXP_RETRIEVE + : ROTTEN_TOMATOES_EXP_RETRIEVE, SkillConstants.FARMING.ordinal()); + if (compostBins[index] != 350) { + player.getItemAssistant().deleteItem(1925, 1); + } + player.getItemAssistant().addItem(finalItem, 1); + player.startAnimation(832, 0); + organicItemAdded[index]--; + if (organicItemAdded[index] == 0) { + resetVariables(index); + } + updateCompostBin(index); + } + + @Override + public void stop() { + player.getPlayerAssistant().resetAnimation(); + } + }, 2); + } + + /* handling the item on object method */ + + public boolean handleItemOnObject(int itemUsed, int objectId, int objectX, + int objectY) { + switch (objectId) { + case 7814: + case 7815: + case 7816: + case 7817: + case 7824: + case 7825: + case 7826: + case 7827: + if (itemUsed == 1925) { + retrieveCompost(CompostBinLocations.forPosition(objectX, + objectY).getCompostIndex()); + } else { + player.getPacketSender().sendMessage( + "You might need some buckets to gather the compost."); + } + return true; + + case 7839: + case 7838: + case 7837: + case 7836: + case 7808: + case 7809: + case 7811: + case 7819: + case 7821: + case 7828: + case 7832: + fillCompostBin(objectX, objectY, itemUsed); + return true; + + } + return false; + } + + /* handling the object click method */ + + public boolean handleObjectClick(int objectId, int objectX, int objectY) { + + switch (objectId) { + + case 7810: + case 7812: + case 7820: + case 7822: + case 7829: + case 7833: + closeCompostBin(CompostBinLocations.forPosition(objectX, objectY) + .getCompostIndex()); + return true; + + case 7813: + case 7823: + openCompostBin(CompostBinLocations.forPosition(objectX, objectY) + .getCompostIndex()); + return true; + + case 7830: + case 7831: + case 7834: + case 7835: + retrieveCompost(CompostBinLocations.forPosition(objectX, objectY) + .getCompostIndex()); + return true; + + } + return false; + } + + /* reseting the compost variables */ + + public void resetVariables(int index) { + compostBins[index] = 0; + compostBinsTimer[index] = 0; + organicItemAdded[index] = 0; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Farmers.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Farmers.java new file mode 100644 index 00000000..d28d3ce0 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Farmers.java @@ -0,0 +1,274 @@ +package com.rebotted.game.content.skills.farming; + +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.game.dialogues.ChatEmotes; +import com.rebotted.game.items.ItemAssistant; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; +/** + * Created by IntelliJ IDEA. User: vayken Date: 19/04/12 Time: 02:42 To change + * this template use File | Settings | File Templates. + */ +public class Farmers { + + public static final String[][] farmingAdvices = { + { "You don't have to buy all your plantpots you know,", + "you can make them yourself on a pottery wheel. If", + "you are a good enough craftsman, that is." }, + { "Don't just throw away your weeds after you've", + "raked a patch - put them in a compost bin and", + "make some compost." }, + { "Tree seeds must be grown in a plantpot of soil", + "into a tree sapling, and then transferred to a", + "tree patch to continue growing to adulthood." }, + { "You can put up to ten potatoes, cabbages, or", + "onions in vegetable sacks, although you can't", + "have a mix in the same sack." }, + { "You can buy all the farming tools from farming", + "shops which can be found close to the allotments" }, + { "You can fill plantpots with soil from Farming", + "patches, if you have a gardening trowel." }, + { "If you want to make your own sacks and baskets", + "you'll need to use the loom that's near the", + "Farming shop in Falador." }, + { "Bittercap mushrooms can only be grown in special", + "patches in Morytania, near the Mort Myre swamp." }, + { "Applying compost to a patch will not only reduce", + "the chance that your crops will get diseased, but", + "you will also grow more crops to harvest." }, + { "Hops are good for brewing ales. I believe there", + "is a brewery up in Keldagrim somewhere." } }; + + public enum FarmersData { + DANTAREA(2324, 41, "allotment", new String[] { "Northern patch", + "Southern patch" }), ELSTAN(2323, 54, "allotment", + new String[] { "North-west patch", "South-East patch" }), LYRA( + 2326, 123, "allotment", new String[] { "North-west patch", + "South-East patch" }), KRAGEN(2325, 99, "allotment", + new String[] { "Northern patch", "Southern patch" }), RHAZIEN( + 2337, 162, "bushes", null), TARIA(2336, 139, "bushes", null), DREVEN( + 2335, 47, "bushes", null), TORREL(2338, 144, "bushes", null), RHONEN( + 2334, 123, "hops", null), SELENA(2332, 134, "hops", null), VASQUEN( + 2333, 153, "hops", null), FRANCIS(2327, 62, "hops", null), BOLONGO( + 2343, 32, "fruitTree", null), ELLENA(2331, 53, "fruitTree", + null), GILEH(2344, 74, "fruitTree", null), GARTH(2330, 70, + "fruitTree", null), HESKEL(2340, 85, "tree", null), ALAIN(2339, + 163, "tree", null), TREZNOR(2341, 146, "tree", null), FAYETH( + 2342, 58, "tree", null); + + private int npcId; + private int shopId; + private String fieldProtected; + private String[] dialogueOptions; + + private static Map npcs = new HashMap(); + + static { + for (FarmersData data : FarmersData.values()) { + npcs.put(data.npcId, data); + } + } + + FarmersData(int npcId, int shopId, String fieldProtected, + String[] dialogueOptions) { + this.npcId = npcId; + this.shopId = shopId; + this.fieldProtected = fieldProtected; + this.dialogueOptions = dialogueOptions; + } + + public static FarmersData forId(int npcId) { + return npcs.get(npcId); + } + + public int getNpcId() { + return npcId; + } + + public String getFieldProtected() { + return fieldProtected; + } + + public String[] getDialogueHandlerOptions() { + return dialogueOptions; + } + + public int getShopId() { + return shopId; + } + } + + public static void protectPlant(Player player, int indexArray, + String fieldType, int npcId, int stage) { + + int index = 0; + int[] payment = new int[2]; + if (stage == 1) { + if (fieldType == "allotment") { + index = Allotments.AllotmentFieldsData.listIndexProtected(npcId).get(indexArray); + if (Allotments.AllotmentData.forId(player.getAllotment().allotmentSeeds[index]) != null) + payment = Allotments.AllotmentData.forId(player.getAllotment().allotmentSeeds[index]).getPaymentToWatch(); + if (player.getAllotment().allotmentStages[index] <= 3) { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.ANNOYED, "I am sorry but you have no crops growing in this patch."); + player.getDialogueHandler().endDialogue(); + } else { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.NOT_INTERESTED, "If you like, but I want " + payment[1] + " " + getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()) + (getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()).endsWith("s") ? "" : "s") + " for that."); + player.nextChat = 3544; + player.setTempInteger(indexArray); + } + } + if (fieldType == "bushes") { + index = Bushes.BushesFieldsData.forId(npcId).getBushesIndex(); + if (Bushes.BushesData.forId(player.getBushes().bushesSeeds[index]) != null) + payment = Bushes.BushesData.forId(player.getBushes().bushesSeeds[index]).getPaymentToWatch(); + if (player.getBushes().bushesStages[index] <= 3) { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.ANNOYED, "I am sorry but you have no crops growing in this patch."); + player.getDialogueHandler().endDialogue(); + } else { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.NOT_INTERESTED, "If you like, but I want " + payment[1] + " " + getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()) + (getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()).endsWith("s") ? "" : "s") + " for that."); + player.nextChat = 3544; + player.setTempInteger(indexArray); + } + } + if (fieldType == "fruitTree") { + index = FruitTree.FruitTreeFieldsData.forId(npcId).getFruitTreeIndex(); + if (FruitTree.FruitTreeData.forId(player.getFruitTrees().fruitTreeSaplings[index]) != null) + payment = FruitTree.FruitTreeData.forId(player.getFruitTrees().fruitTreeSaplings[index]).getPaymentToWatch(); + if (player.getFruitTrees().fruitTreeStages[index] <= 3) { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.ANNOYED, "I am sorry but you have no crops growing in this patch."); + player.getDialogueHandler().endDialogue(); + } else { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.NOT_INTERESTED,"If you like, but I want " + payment[1] + " " + getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()) + (getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()).endsWith("s") ? "" : "s") + " for that."); + player.nextChat = 3544; + player.setTempInteger(indexArray); + } + } + + if (fieldType == "hops") { + index = Hops.HopsFieldsData.forId(npcId).getHopsIndex(); + if (Hops.HopsData.forId(player.getHops().hopsSeeds[index]) != null) + payment = Hops.HopsData.forId(player.getHops().hopsSeeds[index]).getPaymentToWatch(); + if (player.getHops().hopsStages[index] <= 3) { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.ANNOYED, "I am sorry but you have no crops growing in this patch."); + player.getDialogueHandler().endDialogue(); + } else { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.NOT_INTERESTED, "If you like, but I want " + payment[1] + " " + getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()) + (getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()).endsWith("s") ? "" : "s") + " for that."); + player.nextChat = 3544; + player.setTempInteger(indexArray); + } + } + + if (fieldType == "tree") { + index = WoodTrees.TreeFieldsData.forId(npcId).getTreeIndex(); + if (WoodTrees.TreeData.forId(player.getTrees().treeSaplings[index]) != null) + payment = WoodTrees.TreeData.forId(player.getTrees().treeSaplings[index]).getPaymentToWatch(); + if (player.getTrees().treeStages[index] <= 3) { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.ANNOYED, "I am sorry but you have no crops growing in this patch."); + player.getDialogueHandler().endDialogue(); + } else { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.NOT_INTERESTED, "If you like, but I want " + payment[1] + " " + getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()) + (getFinalPaymentString(ItemAssistant.getItemName(payment[0]).toLowerCase()).endsWith("s") ? "" : "s") + " for that."); + player.nextChat = 3544; + player.setTempInteger(indexArray); + } + } + + + } else if (stage == 2) { + if (fieldType == "allotment") { + index = Allotments.AllotmentFieldsData + .listIndexProtected(npcId).get(indexArray); + payment = Allotments.AllotmentData.forId( + player.getAllotment().allotmentSeeds[index]) + .getPaymentToWatch(); + } + if (fieldType == "bushes") { + index = Bushes.BushesFieldsData.forId(npcId).getBushesIndex(); + payment = Bushes.BushesData.forId( + player.getBushes().bushesSeeds[index]) + .getPaymentToWatch(); + } + if (fieldType == "fruitTree") { + index = FruitTree.FruitTreeFieldsData.forId(npcId) + .getFruitTreeIndex(); + payment = Hops.HopsData.forId( + player.getFruitTrees().fruitTreeSaplings[index]) + .getPaymentToWatch(); + } + if (fieldType == "hops") { + index = Hops.HopsFieldsData.forId(npcId).getHopsIndex(); + payment = Hops.HopsData + .forId(player.getHops().hopsSeeds[index]) + .getPaymentToWatch(); + } + if (fieldType == "tree") { + index = WoodTrees.TreeFieldsData.forId(npcId).getTreeIndex(); + payment = WoodTrees.TreeData.forId( + player.getTrees().treeSaplings[index]) + .getPaymentToWatch(); + } + if (player.getItemAssistant().getItemAmount(payment[0]) < payment[1]) { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.DEFAULT, "Sorry, but you do not have the required items", + "I need, for letting me take care of this patch"); + + } else { + if (fieldType == "allotment") { + player.getAllotment().allotmentWatched[index] = true; + } + if (fieldType == "bushes") { + player.getBushes().bushesWatched[index] = true; + } + if (fieldType == "fruitTree") { + player.getFruitTrees().fruitTreeWatched[index] = true; + } + if (fieldType == "hops") { + player.getHops().hopsWatched[index] = true; + } + if (fieldType == "tree") { + player.getTrees().treeWatched[index] = true; + } + player.getItemAssistant().deleteItem(payment[0], payment[1]); + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.DEFAULT, "Here you go, I will be taking care of this patch", + "as soon as it become diseased, I will cure it", + "so you don't have to worry about it."); + } + } + + } + + public static void chopDownTree(Player player, int npcId) { + int index = WoodTrees.TreeFieldsData.forId(npcId).getTreeIndex(); + + if (player.getItemAssistant().getItemCount(995) < 200) { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.DEFAULT, "I am sorry, but you do not have enough money", + "to pay me to chop down this tree."); + + } else { + player.getItemAssistant().deleteItem(995, 200); + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.DEFAULT, "There you go, I have chopped down your tree but I am ", + "keeping the logs and roots as compensation."); + player.getTrees().resetTrees(index); + player.getTrees().treeStages[index] = 3; + player.getTrees().treeTimer[index] = GameEngine.getMinutesCounter(); + player.getTrees().updateTreeStates(); + + } + + } + + public static void sendFarmingAdvice(Player player) { + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.HAPPY_JOYFUL, farmingAdvices[Misc.random(farmingAdvices.length - 1)]); + + } + + public static String getFinalPaymentString(String word) { + if (word.contains("(5)")) + return "baskets of " + word.replace("(5)", ""); + if (word.contains("(10)")) + return "sacks of " + word.replace("(10)", ""); + return word; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Farming.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Farming.java index 3c157a55..b74b365e 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Farming.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Farming.java @@ -2,24 +2,296 @@ package com.rebotted.game.content.skills.farming; import com.rebotted.game.players.Player; -/** - * Farming - * @author Andrew (Mr Extremez) - */ - public class Farming { - - public static void openGuide(Player player, int objectType) { - if (Flowers.isFlower(player, objectType)) { - player.getSkillInterfaces().farmingComplex(6); - player.getSkillInterfaces().selected = 20; - } else if (Herbs.isHerb(player, objectType)) { - player.getSkillInterfaces().farmingComplex(7); - player.getSkillInterfaces().selected = 20; - } else if (Allotments.isAllotment(player, objectType)) { - player.getSkillInterfaces().farmingComplex(1); - player.getSkillInterfaces().selected = 20; - } + + public static void processCalc(Player p) { + p.getAllotment().doCalculations(); + p.getBushes().doCalculations(); + p.getFlowers().doCalculations(); + p.getFruitTrees().doCalculations(); + p.getHerbs().doCalculations(); + p.getHops().doCalculations(); + p.getSpecialPlantOne().doCalculations(); + p.getSpecialPlantTwo().doCalculations(); + p.getTrees().doCalculations(); } + public static boolean prepareCrop(Player player, int item, int id, int x, + int y) { + // plant pot + if (player.getSeedling().fillPotWithSoil(item, x, y)) { + return true; + } + // // allotments + if (player.getAllotment().curePlant(x, y, item)) { + return true; + } + if (player.getAllotment().putCompost(x, y, item)) { + return true; + } + if (player.getAllotment().clearPatch(x, y, item)) { + return true; + } + if (item >= 3422 && item <= 3428 && id == 4090) { + player.getItemAssistant().deleteItem(item, 1); + player.getItemAssistant().addItem(item + 8, 1); + player.startAnimation(832); + player.getPacketSender() + .sendMessage( + "You put the olive oil on the fire, and turn it into sacred oil."); + return true; + } + if (item <= 5340 && item > 5332) { + if (player.getAllotment().waterPatch(x, y, item)) { + return true; + } + } + if (player.getAllotment().plantSeed(x, y, item)) { + return true; + } + // flowers + if (player.getFlowers().plantScareCrow(x, y, item)) { + return true; + } + if (player.getFlowers().curePlant(x, y, item)) { + return true; + } + if (player.getFlowers().putCompost(x, y, item)) { + return true; + } + if (player.getFlowers().clearPatch(x, y, item)) { + return true; + } + if (item <= 5340 && item > 5332) { + if (player.getFlowers().waterPatch(x, y, item)) { + return true; + } + } + if (player.getFlowers().plantSeed(x, y, item)) { + return true; + } + if (player.getCompost().handleItemOnObject(item, id, x, y)) { + return true; + } + // herbs + if (player.getHerbs().curePlant(x, y, item)) { + return true; + } + if (player.getHerbs().putCompost(x, y, item)) { + return true; + } + if (player.getHerbs().clearPatch(x, y, item)) { + return true; + } + if (player.getHerbs().plantSeed(x, y, item)) { + return true; + } + // hops + if (player.getHops().curePlant(x, y, item)) { + return true; + } + if (player.getHops().putCompost(x, y, item)) { + return true; + } + if (player.getHops().clearPatch(x, y, item)) { + return true; + } + if (item <= 5340 && item > 5332) + if (player.getHops().waterPatch(x, y, item)) { + return true; + } + if (player.getHops().plantSeed(x, y, item)) { + return true; + } + // bushes + if (player.getBushes().curePlant(x, y, item)) { + return true; + } + if (player.getBushes().putCompost(x, y, item)) { + return true; + } + + if (player.getBushes().clearPatch(x, y, item)) { + return true; + } + if (player.getBushes().plantSeed(x, y, item)) { + return true; + } + // trees + if (player.getTrees().pruneArea(x, y, item)) { + return true; + } + if (player.getTrees().putCompost(x, y, item)) { + return true; + } + if (player.getTrees().plantSapling(x, y, item)) { + return true; + } + if (player.getTrees().clearPatch(x, y, item)) { + return true; + } + // fruit trees + if (player.getFruitTrees().pruneArea(x, y, item)) { + return true; + } + if (player.getFruitTrees().putCompost(x, y, item)) { + return true; + } + if (player.getFruitTrees().clearPatch(x, y, item)) { + return true; + } + if (player.getFruitTrees().plantSapling(x, y, item)) { + return true; + } + // special plant one + if (player.getSpecialPlantOne().curePlant(x, y, item)) { + return true; + } + if (player.getSpecialPlantOne().putCompost(x, y, item)) { + return true; + } + if (player.getSpecialPlantOne().clearPatch(x, y, item)) { + return true; + } + if (player.getSpecialPlantOne().plantSapling(x, y, item)) { + return true; + } + // Special plant two + if (player.getSpecialPlantTwo().curePlant(x, y, item)) { + return true; + } + if (player.getSpecialPlantTwo().putCompost(x, y, item)) { + return true; + } + if (player.getSpecialPlantTwo().clearPatch(x, y, item)) { + return true; + } + if (player.getSpecialPlantTwo().plantSeeds(x, y, item)) { + return true; + } + // player.sendMessage("Farming disabled - coming soon"); + return false; + } + + public static boolean inspectObject(Player player, int x, int y) { + // allotments + if (player.getAllotment().inspect(x, y)) { + return true; + } // flowers + if (player.getFlowers().inspect(x, y)) { + return true; + } + // herbs + if (player.getHerbs().inspect(x, y)) { + return true; + } + // hops + if (player.getHops().inspect(x, y)) { + return true; + } + // bushes + if (player.getBushes().inspect(x, y)) { + return true; + } + // trees + if (player.getTrees().inspect(x, y)) { + return true; + } + // fruit trees + if (player.getFruitTrees().inspect(x, y)) { + return true; + } + // special plant one + if (player.getSpecialPlantOne().inspect(x, y)) { + return true; + } + // special plant two + if (player.getSpecialPlantTwo().inspect(x, y)) { + return true; + } + return false; + } + + public static boolean guide(Player player, int x, int y) { + // allotments + if (player.getAllotment().guide(x, y)) { + return true; + } // flowers + if (player.getFlowers().guide(x, y)) { + return true; + } + // herbs + if (player.getHerbs().guide(x, y)) { + return true; + } + // hops + if (player.getHops().guide(x, y)) { + return true; + } + // bushes + if (player.getBushes().guide(x, y)) { + return true; + } + // trees + if (player.getTrees().guide(x, y)) { + return true; + } + // fruit trees + if (player.getFruitTrees().guide(x, y)) { + return true; + } + // special plant one + if (player.getSpecialPlantOne().guide(x, y)) { + return true; + } + // special plant two + if (player.getSpecialPlantTwo().guide(x, y)) { + return true; + } + return false; + } + + public static boolean harvest(Player player, int x, int y) { + // allotments + + if (player.getAllotment().harvest(x, y)) { + return true; + } + // flowers + if (player.getFlowers().harvest(x, y)) { + return true; + } + // herbs + if (player.getHerbs().harvest(x, y)) { + return true; + } + // hops + if (player.getHops().harvest(x, y)) { + return true; + } + // bushes + if (player.getBushes().harvestOrCheckHealth(x, y)) { + return true; + } + // trees + if (player.getTrees().checkHealth(x, y)) { + return true; + } + if (player.getTrees().cut(x, y)) { + return true; + } + // fruit trees + if (player.getFruitTrees().harvestOrCheckHealth(x, y)) { + return true; + } + // special plant one + if (player.getSpecialPlantOne().harvestOrCheckHealth(x, y)) { + return true; + } + // special plant two + if (player.getSpecialPlantTwo().harvestOrCheckHealth(x, y)) { + return true; + } + return false; + } } diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FarmingConstants.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FarmingConstants.java index 693c8079..e49902fd 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FarmingConstants.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FarmingConstants.java @@ -1,7 +1,25 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ package com.rebotted.game.content.skills.farming; -public class FarmingConstants { - +import java.awt.Point; + +/** + * + * @author ArrowzFtw + */ + +/** + * Created by IntelliJ IDEA. User: vayken Date: 25/02/12 Time: 16:39 To change + * this template use File | Settings | File Templates. + */ +public class FarmingConstants {// todo farmers watching crops + // payment to farmer + // todo sack making with jute, sack filling with + // items + public static final int WATERING_CAN_ANIM = 2293; public static final int RAKING_ANIM = 2273; public static final int SPADE_ANIM = 830; @@ -13,6 +31,10 @@ public class FarmingConstants { public static final int FILLING_POT_ANIM = 2287; public static final int PLANTING_POT_ANIM = 2272; public static final int PRUNING_ANIM = 2275; + public static final int GRASS_OBJECT = 8389; + public static final int HERB_OBJECT = 8143; + public static final int HERB_PATCH_DEPLETED = 8388; + public static final int RAKE = 5341; public static final int SEED_DIBBER = 5343; @@ -21,5 +43,16 @@ public class FarmingConstants { public static final int SECATEURS = 5329; public static final int MAGIC_SECATEURS = 7409; - public static final int[] WATERED_SAPPLING = {5364, 5365, 5366, 5367, 5368, 5369, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495}; + public static final int[] WATERED_SAPPLING = { 5364, 5365, 5366, 5367, + 5368, 5369, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495 }; + + public static boolean inRangeArea(Point base, Point top, Point point) { + return point.getX() >= base.getX() && point.getY() >= base.getY() + && point.getX() <= top.getX() && point.getY() <= top.getY(); + } + + public static boolean inRangeArea(Point base, Point top, int x, int y) { + return x >= base.getX() && y >= base.getY() && x <= top.getX() + && y <= top.getY(); + } } diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FarmingTask.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FarmingTask.java new file mode 100644 index 00000000..254432eb --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FarmingTask.java @@ -0,0 +1,19 @@ +package com.rebotted.game.content.skills.farming; + +import com.rebotted.game.players.Player; +import com.rebotted.tick.Tick; + +public class FarmingTask extends Tick { + + private Player player; + + public FarmingTask(Player player) { + super(10); + this.player = player; + } + + @Override + protected void execute() { + Farming.processCalc(player); + } +} \ No newline at end of file diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Flowers.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Flowers.java index 8ddf74e2..89b0644d 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Flowers.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Flowers.java @@ -1,23 +1,895 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ package com.rebotted.game.content.skills.farming; -import com.rebotted.game.players.Player; +/** + * + * @author ArrowzFtw + */ +import java.awt.Point; +import java.util.HashMap; +import java.util.Map; +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; /** - * Flowers - * @author Andrew (I'm A Boss on Rune-Server and Mr Extremez on Mopar & Runelocus) + * Created by IntelliJ IDEA. User: vayken Date: 24/02/12 Time: 20:34 To change + * this template use File | Settings | File Templates. */ +public class Flowers { // todo scarecrow 6059 -public class Flowers { - - private static final int[] FLOWER_PATCH = {7847, 7848}; - - public static boolean isFlower(Player player, int objectType) { - for (int i = 0; i < FLOWER_PATCH.length; i++) { - if (objectType == FLOWER_PATCH[i]) { - return true; + private Player player; + + // set of global constants for Farming + + private static final double WATERING_CHANCE = 0.5; + private static final double COMPOST_CHANCE = 0.9; + private static final double SUPERCOMPOST_CHANCE = 0.7; + private static final double CLEARING_EXPERIENCE = 4; + public static final int SCARECROW = 6059; + + public Flowers(Player player) { + this.player = player; + } + + // Farming data + public int[] flowerStages = new int[4]; + public int[] flowerSeeds = new int[4]; + public int[] flowerState = new int[4]; + public long[] flowerTimer = new long[4]; + public double[] diseaseChance = { 1, 1, 1, 1 }; + public boolean[] hasFullyGrown = { false, false, false, false }; + + /* set of the constants for the patch */ + + // states - 2 bits plant - 6 bits + public static final int GROWING = 0x00; + public static final int WATERED = 0x01; + public static final int DISEASED = 0x02; + public static final int DEAD = 0x03; + + public static final int FLOWER_PATCH_CONFIGS = 508; + + /* This is the enum holding the seeds info */ + + public enum FlowerData { + + MARIGOLD(5096, 6010, 2, 20, 0.35, 8.5, 47, 0x08, 0x0c), ROSEMARY(5097, + 6014, 11, 20, 0.32, 12, 66.5, 0x0d, 0x11), NASTURTIUM(5098, + 6012, 24, 20, 0.30, 19.5, 111, 0x12, 0x16), WOAD(5099, 1793, + 25, 20, 0.27, 20.5, 115.5, 0x17, 0x1b), LIMPWURT(5100, 225, 26, + 25, 21.5, 8.5, 120, 0x1c, 0x20), ; + + private int seedId; + private int harvestId; + private int levelRequired; + private int growthTime; + private double diseaseChance; + private double plantingXp; + private double harvestXp; + private int startingState; + private int endingState; + + private static Map seeds = new HashMap(); + + static { + for (FlowerData data : FlowerData.values()) { + seeds.put(data.seedId, data); } } + + FlowerData(int seedId, int harvestId, int levelRequired, + int growthTime, double diseaseChance, double plantingXp, + double harvestXp, int startingState, int endingState) { + this.seedId = seedId; + this.harvestId = harvestId; + this.levelRequired = levelRequired; + this.growthTime = growthTime; + this.diseaseChance = diseaseChance; + this.plantingXp = plantingXp; + this.harvestXp = harvestXp; + this.startingState = startingState; + this.endingState = endingState; + } + + public static FlowerData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public int getHarvestId() { + return harvestId; + } + + public int getLevelRequired() { + return levelRequired; + } + + public int getGrowthTime() { + return growthTime; + } + + public double getDiseaseChance() { + return diseaseChance; + } + + public double getPlantingXp() { + return plantingXp; + } + + public double getHarvestXp() { + return harvestXp; + } + + public int getStartingState() { + return startingState; + } + + public int getEndingState() { + return endingState; + } + } + + /* This is the enum data about the different patches */ + + public enum FlowerFieldsData { + ARDOUGNE(0, + new Point[] { new Point(2666, 3374), new Point(2667, 3375) }), PHASMATYS( + 1, new Point[] { new Point(3601, 3525), new Point(3602, 3526) }), FALADOR( + 2, new Point[] { new Point(3054, 3307), new Point(3055, 3308) }), CATHERBY( + 3, new Point[] { new Point(2809, 3463), new Point(2810, 3464) }); + + private int flowerIndex; + private Point[] flowerPosition; + + FlowerFieldsData(int flowerIndex, Point[] flowerPosition) { + this.flowerIndex = flowerIndex; + this.flowerPosition = flowerPosition; + } + + public static FlowerFieldsData forIdPosition(Point point) { + for (FlowerFieldsData flowerFieldsData : FlowerFieldsData.values()) { + if (FarmingConstants.inRangeArea( + flowerFieldsData.getFlowerPosition()[0], + flowerFieldsData.getFlowerPosition()[1], point)) { + return flowerFieldsData; + } + } + return null; + } + + public int getFlowerIndex() { + return flowerIndex; + } + + public Point[] getFlowerPosition() { + return flowerPosition; + } + } + + /* This is the enum that hold the different data for inspecting the plant */ + + public enum InspectData { + + MARIGOLD(5096, new String[][] { + { "The seeds have only just been planted." }, + { "The marigold plants have developed leaves." }, + { "The marigold plants have begun to grow their", + "flowers. The new flowers are orange and small at", + "first." }, + { "The marigold plants are larger, and more", + "developed in their petals." }, + { "The marigold plants are ready to harvest. Their", + "flowers are fully matured." } }), ROSEMARY(5097, + new String[][] { + { "The seeds have only just been planted." }, + { "The rosemary plant is taller than before." }, + { "The rosemary plant is bushier and taller than", + "before." }, + { "The rosemary plant is developing a flower bud at", + "its top." }, + { "The plant is ready to harvest. The rosemary", + "plant's flower has opened." } }), NASTURTIUM( + 5098, + new String[][] { + { "The nasturtium seed has only just been planted." }, + { "The nasturtium plants have started to develop", + "leaves." }, + { "The nasturtium plants have grown more leaves,", + "and nine flower buds." }, + { "The nasturtium plants open their flower buds." }, + { + "The plants are ready to harvest. The nasturtium", + "plants grow larger than before and the flowers", + "fully open." } }), WOAD(5099, new String[][] { + { "The woad seed has only just been planted." }, + { "The woad plant produces more stalks, that split", + "in tow near the top." }, + { "The woad plant grows more segments from its", + "intitial stalks." }, + { "The woad plant develops flower buds on the end", + "of each of its stalks." }, + { "The woad plant is ready to harvest. The plant has", + "all of its stalks pointing directly up, with", + "all flowers open." } }), LIMPWURT( + 5100, + new String[][] { + { "The seed has only just been planted." }, + { "The limpwurt plant produces more roots." }, + { "The limpwurt plant produces an unopened pink", + "flower bud and continues to grow larger." }, + { "The limpwurt plant grows larger, with more loops", + "in its roots. The flower bud is still unopened." }, + { + "The limpwurt plant is ready to harvest. The", + "flower finally opens wide, with a spike in the", + "middle." } }); + private int seedId; + private String[][] messages; + + private static Map seeds = new HashMap(); + + static { + for (InspectData data : InspectData.values()) { + seeds.put(data.seedId, data); + } + } + + InspectData(int seedId, String[][] messages) { + this.seedId = seedId; + this.messages = messages; + } + + public static InspectData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public String[][] getMessages() { + return messages; + } + } + + /* update all the patch states */ + + public void updateFlowerStates() { + // ardougne - phasmatys - falador - catherby + int[] configValues = new int[flowerStages.length]; + + int configValue; + for (int i = 0; i < flowerStages.length; i++) { + configValues[i] = getConfigValue(flowerStages[i], flowerSeeds[i], + flowerState[i], i); + } + + configValue = (configValues[0] << 16) + (configValues[1] << 8 << 16) + + configValues[2] + (configValues[3] << 8); + player.getPacketSender().sendConfig(FLOWER_PATCH_CONFIGS, configValue); + + } + + /* getting the different config values */ + + public int getConfigValue(int flowerStage, int seedId, int plantState, + int index) { + if (flowerSeeds[index] >= 0x21 && flowerSeeds[index] <= 0x24 + && flowerStages[index] > 3) { + return (GROWING << 6) + flowerSeeds[index]; + } + FlowerData flowerData = FlowerData.forId(seedId); + switch (flowerStage) { + case 0:// weed + return (GROWING << 6) + 0x00; + case 1:// weed cleared + return (GROWING << 6) + 0x01; + case 2: + return (GROWING << 6) + 0x02; + case 3: + return (GROWING << 6) + 0x03; + } + if (flowerData == null) { + return -1; + } + if (flowerData.getEndingState() == flowerData.getStartingState() + + flowerStage - 2) { + hasFullyGrown[index] = true; + } + return (getPlantState(plantState) << 6) + flowerData.getStartingState() + + flowerStage - 4; + } + + /* getting the plant states */ + + public int getPlantState(int plantState) { + switch (plantState) { + case 0: + return GROWING; + case 1: + return WATERED; + case 2: + return DISEASED; + case 3: + return DEAD; + } + return -1; + } + + /* calculating the disease chance and making the plant grow */ + + public void doCalculations() { + for (int i = 0; i < flowerSeeds.length; i++) { + if (flowerStages[i] > 0 && flowerStages[i] <= 3 + && GameEngine.getMinutesCounter() - flowerTimer[i] >= 5) { + flowerStages[i]--; + flowerTimer[i] = GameEngine.getMinutesCounter(); + updateFlowerStates(); + } + if (GameEngine.getMinutesCounter() - flowerTimer[i] >= 5 + && flowerSeeds[i] > 0x21 && flowerSeeds[i] <= 0x24) { + flowerSeeds[i]--; + updateFlowerStates(); + return; + } + FlowerData flowerData = FlowerData.forId(flowerSeeds[i]); + if (flowerData == null) { + continue; + } + + long difference = GameEngine.getMinutesCounter() - flowerTimer[i]; + long growth = flowerData.getGrowthTime(); + int nbStates = flowerData.getEndingState() + - flowerData.getStartingState(); + int state = (int) (difference * nbStates / growth); + if (flowerState[i] == 3 || flowerSeeds[i] == 0x21 + || flowerTimer[i] == 0 || state > nbStates) { + continue; + } + + if (4 + state != flowerStages[i]) { + flowerStages[i] = 4 + state; + doStateCalculation(i); + updateFlowerStates(); + } + } + } + + /* calculations about the diseasing chance */ + + public void doStateCalculation(int index) { + if (flowerState[index] == 3) { + return; + } + // if the patch is diseased, it dies, if its watched by a farmer, it + // goes back to normal + if (flowerState[index] == 2) { + flowerState[index] = 3; + } + + if (flowerState[index] == 1 || flowerState[index] == 5 + && flowerStages[index] != 3) { + diseaseChance[index] *= 2; + flowerState[index] = 0; + } + if (flowerState[index] == 0 && flowerStages[index] >= 5 + && !hasFullyGrown[index]) { + FlowerData flowerData = FlowerData.forId(flowerSeeds[index]); + if (flowerData == null) { + return; + } + double chance = diseaseChance[index] + * flowerData.getDiseaseChance(); + int maxChance = (int) (chance * 100); + + if (Misc.random(100) <= maxChance) { + flowerState[index] = 2; + } + } + } + + /* watering the patch */ + + public boolean waterPatch(int objectX, int objectY, int itemId) { + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + if (flowerFieldsData == null) { + return false; + } + FlowerData flowerData = FlowerData.forId(flowerSeeds[flowerFieldsData + .getFlowerIndex()]); + if (flowerData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (flowerState[flowerFieldsData.getFlowerIndex()] == 1 + || flowerStages[flowerFieldsData.getFlowerIndex()] <= 1 + || flowerStages[flowerFieldsData.getFlowerIndex()] == flowerData + .getEndingState() - flowerData.getStartingState() + 4) { + player.getPacketSender().sendMessage("This patch doesn't need watering."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(itemId == 5333 ? itemId - 2 : itemId - 1, 1); + + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a seed dibber to plant seed here."); + return true; + } + player.getPacketSender().sendMessage("You water the patch."); + player.startAnimation( + FarmingConstants.WATERING_CAN_ANIM); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[flowerFieldsData.getFlowerIndex()] *= WATERING_CHANCE; + flowerState[flowerFieldsData.getFlowerIndex()] = 1; + container.stop(); + } + + @Override + public void stop() { + updateFlowerStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 5); + return true; + } + + /* clearing the patch with a rake of a spade */ + + public boolean clearPatch(int objectX, int objectY, int itemId) { + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + int finalAnimation; + int finalDelay; + if (flowerFieldsData == null + || (itemId != FarmingConstants.RAKE && itemId != FarmingConstants.SPADE)) { + return false; + } + if (flowerStages[flowerFieldsData.getFlowerIndex()] == 3) { + return true; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (flowerStages[flowerFieldsData.getFlowerIndex()] <= 3) { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a rake to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.RAKING_ANIM; + finalDelay = 5; + } + } else { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.SPADE_ANIM; + finalDelay = 3; + } + } + final int animation = finalAnimation; + player.stopPlayer(true); + player.startAnimation(animation); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.startAnimation(animation); + if (flowerStages[flowerFieldsData.getFlowerIndex()] <= 2) { + flowerStages[flowerFieldsData.getFlowerIndex()]++; + player.getItemAssistant().addItem(6055, 1); + } else { + flowerStages[flowerFieldsData.getFlowerIndex()] = 3; + container.stop(); + } + player.getPlayerAssistant().addSkillXP(CLEARING_EXPERIENCE, SkillConstants.FARMING.ordinal()); + flowerTimer[flowerFieldsData.getFlowerIndex()] = GameEngine + .getMinutesCounter(); + updateFlowerStates(); + if (flowerStages[flowerFieldsData.getFlowerIndex()] == 3) { + container.stop(); + return; + } + } + + @Override + public void stop() { + resetFlowers(flowerFieldsData.getFlowerIndex()); + player.getPacketSender().sendMessage("You clear the patch."); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, finalDelay); + return true; + + } + + /* planting the seeds */ + + public boolean plantSeed(int objectX, int objectY, final int seedId) { + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + final FlowerData flowerData = FlowerData.forId(seedId); + if (flowerFieldsData == null || flowerData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (flowerStages[flowerFieldsData.getFlowerIndex()] != 3) { + player.getDialogueHandler().sendStatement( + "You can't plant a seed here."); + return false; + } + if (flowerData.getLevelRequired() > player.playerLevel[SkillConstants.FARMING.ordinal()]) { + player.getDialogueHandler().sendStatement( "You need a farming level of " + + flowerData.getLevelRequired() + + " to plant this seed."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SEED_DIBBER)) { + player.getDialogueHandler().sendStatement( + "You need a seed dibber to plant seed here."); + return true; + } + + player.startAnimation(FarmingConstants.SEED_DIBBING); + flowerStages[flowerFieldsData.getFlowerIndex()] = 4; + player.getItemAssistant().deleteItem(seedId, 1); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + flowerState[flowerFieldsData.getFlowerIndex()] = 0; + flowerSeeds[flowerFieldsData.getFlowerIndex()] = seedId; + flowerTimer[flowerFieldsData.getFlowerIndex()] = GameEngine + .getMinutesCounter(); + player.getPlayerAssistant().addSkillXP(flowerData.getPlantingXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateFlowerStates(); + player.stopPlayer(false); + } + }, 3); + return true; + } + + @SuppressWarnings("unused") + private void displayAll() { + for (int i = 0; i < flowerStages.length; i++) { + System.out.println("index : " + i); + System.out.println("state : " + flowerState[i]); + System.out.println("seeds : " + flowerSeeds[i]); + System.out.println("level : " + flowerStages[i]); + System.out.println("timer : " + flowerTimer[i]); + System.out.println("disease chance : " + diseaseChance[i]); + System.out + .println("-----------------------------------------------------------------"); + } + } + + /* harvesting the plant resulted */ + + public boolean harvest(int objectX, int objectY) { + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + if (flowerFieldsData == null) { + return false; + } + final FlowerData flowerData = FlowerData + .forId(flowerSeeds[flowerFieldsData.getFlowerIndex()]); + if (flowerData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to harvest here."); + return true; + } + + player.startAnimation(FarmingConstants.SPADE_ANIM); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + resetFlowers(flowerFieldsData.getFlowerIndex()); + flowerStages[flowerFieldsData.getFlowerIndex()] = 3; + flowerTimer[flowerFieldsData.getFlowerIndex()] = GameEngine + .getMinutesCounter(); + player.startAnimation( + FarmingConstants.SPADE_ANIM); + player.getPacketSender().sendMessage( + "You harvest the crop, and get some vegetables."); + player.getItemAssistant().addItem(flowerData.getHarvestId(), flowerData.getHarvestId() == 5099 || flowerData.getHarvestId() == 5100 ? 3 : 1); + player.getPlayerAssistant().addSkillXP(flowerData.getHarvestXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateFlowerStates(); + player.getPlayerAssistant().resetAnimation(); + } + }, 2); + return true; + } + + /* putting compost onto the plant */ + + public boolean putCompost(int objectX, int objectY, final int itemId) { + if (itemId != 6032 && itemId != 6034) { + return false; + } + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + if (flowerFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (flowerStages[flowerFieldsData.getFlowerIndex()] != 3 + || flowerState[flowerFieldsData.getFlowerIndex()] == 5) { + player.getPacketSender().sendMessage("This patch doesn't need compost."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(1925, 1); + + player.getPacketSender().sendMessage( + "You pour some " + (itemId == 6034 ? "super" : "") + + "compost on the patch."); + player.startAnimation(FarmingConstants.PUTTING_COMPOST); + player.getPlayerAssistant().addSkillXP(itemId == 6034 ? Compost.SUPER_COMPOST_EXP_USE : Compost.COMPOST_EXP_USE, SkillConstants.FARMING.ordinal()); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[flowerFieldsData.getFlowerIndex()] *= itemId == 6032 ? COMPOST_CHANCE + : SUPERCOMPOST_CHANCE; + flowerState[flowerFieldsData.getFlowerIndex()] = 5; + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + return true; + } + + /* inspecting a plant */ + + public boolean inspect(int objectX, int objectY) { + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + if (flowerFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + final InspectData inspectData = InspectData + .forId(flowerSeeds[flowerFieldsData.getFlowerIndex()]); + final FlowerData flowerData = FlowerData + .forId(flowerSeeds[flowerFieldsData.getFlowerIndex()]); + if (flowerState[flowerFieldsData.getFlowerIndex()] == 2) { + player.getDialogueHandler().sendStatement("This plant is diseased. Use a plant cure on it to cure it, ", + "or clear the patch with a spade."); + return true; + } else if (flowerState[flowerFieldsData.getFlowerIndex()] == 3) { + player.getDialogueHandler().sendStatement("This plant is dead. You did not cure it while it was diseased.", + "Clear the patch with a spade."); + return true; + } + if (flowerStages[flowerFieldsData.getFlowerIndex()] == 0) { + player.getDialogueHandler().sendStatement( + "This is a flower patch. The soil has not been treated.", + "The patch needs weeding."); + } else if (flowerStages[flowerFieldsData.getFlowerIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This is a flower patch. The soil has not been treated.", + "The patch is empty and weeded."); + } else if (inspectData != null && flowerData != null) { + player.getPacketSender().sendMessage( + "You bend down and start to inspect the patch..."); + + player.startAnimation(1331); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (flowerStages[flowerFieldsData.getFlowerIndex()] - 4 < inspectData + .getMessages().length - 2) { + player.getDialogueHandler().sendStatement( inspectData + .getMessages()[flowerStages[flowerFieldsData + .getFlowerIndex()] - 4]); + } else if (flowerStages[flowerFieldsData.getFlowerIndex()] < flowerData + .getEndingState() + - flowerData.getStartingState() + + 4) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 2]); + } else { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 1]); + } + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(1332); + player.stopPlayer(false); + // player.reset(); + } + }, 5); + } + return true; + } + + /* opening the corresponding guide about the patch */ + + public boolean guide(int objectX, int objectY) { + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + if (flowerFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + player.getSkillInterfaces().farmingComplex(6); + player.getSkillInterfaces().selected = 20; + return true; + } + + /* Curing the plant */ + + public boolean curePlant(int objectX, int objectY, int itemId) { + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + if (flowerFieldsData == null || itemId != 6036) { + return false; + } + final FlowerData flowerData = FlowerData + .forId(flowerSeeds[flowerFieldsData.getFlowerIndex()]); + if (flowerData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (flowerState[flowerFieldsData.getFlowerIndex()] != 2) { + player.getPacketSender().sendMessage("This plant doesn't need to be cured."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(229, 1); + player.startAnimation(FarmingConstants.CURING_ANIM); + flowerState[flowerFieldsData.getFlowerIndex()] = 0; + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender().sendMessage( + "You cure the plant with a plant cure."); + container.stop(); + } + + @Override + public void stop() { + updateFlowerStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + + return true; + + } + + /* Planting scarecrow to push off the birds */ + + public boolean plantScareCrow(int objectX, int objectY, int itemId) { + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + if (flowerFieldsData == null || itemId != SCARECROW) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (flowerStages[flowerFieldsData.getFlowerIndex()] != 3) { + player.getPacketSender().sendMessage( + "You need to clear the patch before planting a scarecrow"); + return false; + } + player.getItemAssistant().deleteItem(SCARECROW, 1); + player.startAnimation(832); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender() + .sendMessage( + "You put a scarecrow on the flower patch, and some weeds start to grow around it."); + flowerSeeds[flowerFieldsData.getFlowerIndex()] = 0x24; + flowerStages[flowerFieldsData.getFlowerIndex()] = 4; + flowerTimer[flowerFieldsData.getFlowerIndex()] = GameEngine + .getMinutesCounter(); + container.stop(); + } + + @Override + public void stop() { + updateFlowerStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 2); + return true; + } + + /* reseting the patches */ + + private void resetFlowers(int index) { + flowerSeeds[index] = 0; + flowerState[index] = 0; + diseaseChance[index] = 1; + } + + /* checking if the patch is raked */ + + public boolean checkIfRaked(int objectX, int objectY) { + final FlowerFieldsData flowerFieldsData = FlowerFieldsData + .forIdPosition(new Point(objectX, objectY)); + if (flowerFieldsData == null) + return false; + if (flowerStages[flowerFieldsData.getFlowerIndex()] == 3) + return true; return false; } diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FruitTree.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FruitTree.java new file mode 100644 index 00000000..49ad26fa --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/FruitTree.java @@ -0,0 +1,1005 @@ +package com.rebotted.game.content.skills.farming; + +/** + * + * @author ArrowzFtw + */ +import java.awt.Point; +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; + +/** + * Created by IntelliJ IDEA. User: vayken Date: 24/02/12 Time: 20:34 To change + * this template use File | Settings | File Templates. + */ +public class FruitTree { + + private Player player; + + // set of global constants for Farming + + private static final double COMPOST_CHANCE = 0.9; + private static final double SUPERCOMPOST_CHANCE = 0.7; + private static final double CLEARING_EXPERIENCE = 4; + + public FruitTree(Player player) { + this.player = player; + } + + // Farming data + public int[] fruitTreeStages = new int[4]; + public int[] fruitTreeSaplings = new int[4]; + public int[] fruitTreeState = new int[4]; + public long[] fruitTreeTimer = new long[4]; + public double[] diseaseChance = { 1, 1, 1, 1 }; + public boolean[] hasFullyGrown = { false, false, false, false }; + public boolean[] fruitTreeWatched = { false, false, false, false, false, + false, false, false }; + + public static final int MAIN_FRUIT_TREE_CONFIG = 503; + + /* This is the enum holding the seeds info */ + + public enum FruitTreeData { + APPLE(5496, 1955, 1, 27, new int[] { 5986, 9 }, 120, 0.20, 22, 8.5, + 0x08, 0x14, 0x0e, 0x21, 0x22, 1199.5, 12, 18), BANANA(5497, + 1963, 1, 33, new int[] { 5386, 4 }, 120, 0.20, 28, 10.5, 0x23, + 0x2f, 0x29, 0x3c, 0x3d, 1750.5, 12, 18), ORANGE(5498, 2108, 1, + 39, new int[] { 5406, 3 }, 120, 0.20, 35.5, 13.5, 0x48, 0x54, + 0x4e, 0x61, 0x62, 2470.2, 12, 18), CURRY(5499, 5970, 1, 42, + new int[] { 5416, 5 }, 120, 0.25, 40, 15, 0x63, 0x6f, 0x69, + 0x7c, 0x7d, 2906.9, 12, 18), PINEAPPLE(5500, 2114, 1, 51, + new int[] { 5982, 10 }, 120, 0.25, 57, 21.5, 0x88, 0x94, 0x8e, + 0xa1, 0xa2, 4605.7, 12, 18), PAPAYA(5501, 5972, 1, 57, + new int[] { 2114, 10 }, 120, 0.25, 72, 27, 0xa3, 0xaf, 0xa9, + 0xbc, 0xbd, 6146.4, 12, 18), PALM(5502, 5974, 1, 68, new int[] { + 5972, 15 }, 120, 0.25, 170.5, 41.5, 0xc8, 0xd4, 0xce, 0xe1, + 0xe2, 10150.1, 12, 18); + + private int saplingId; + private int harvestId; + private int saplingAmount; + private int levelRequired; + private int[] paymentToWatch; + private int growthTime; + private double diseaseChance; + private double plantingXp; + private double harvestXp; + private int startingState; + private int endingState; + private int limitState; + private int stumpState; + private int checkHealthState; + private double checkHealthExperience; + private int diseaseDiffValue; + private int deathDiffValue; + + private static Map saplings = new HashMap(); + + static { + for (FruitTreeData data : FruitTreeData.values()) { + saplings.put(data.saplingId, data); + } + } + + FruitTreeData(int saplingId, int harvestId, int saplingAmount, + int levelRequired, int[] paymentToWatch, int growthTime, + double diseaseChance, double plantingXp, double harvestXp, + int startingState, int endingState, int limitState, + int stumpState, int checkHealthState, + double checkHealthExperience, int diseaseDiffValue, + int deathDiffValue) { + this.saplingId = saplingId; + this.harvestId = harvestId; + this.saplingAmount = saplingAmount; + this.levelRequired = levelRequired; + this.paymentToWatch = paymentToWatch; + this.growthTime = growthTime; + this.diseaseChance = diseaseChance; + this.plantingXp = plantingXp; + this.harvestXp = harvestXp; + this.startingState = startingState; + this.endingState = endingState; + this.limitState = limitState; + this.stumpState = stumpState; + this.checkHealthState = checkHealthState; + this.checkHealthExperience = checkHealthExperience; + this.diseaseDiffValue = diseaseDiffValue; + this.deathDiffValue = deathDiffValue; + } + + public static FruitTreeData forId(int saplingId) { + return saplings.get(saplingId); + } + + public int getSapplingId() { + return saplingId; + } + + public int getHarvestId() { + return harvestId; + } + + public int getSapplingAmount() { + return saplingAmount; + } + + public int getLevelRequired() { + return levelRequired; + } + + public int[] getPaymentToWatch() { + return paymentToWatch; + } + + public int getGrowthTime() { + return growthTime; + } + + public double getDiseaseChance() { + return diseaseChance; + } + + public double getPlantingXp() { + return plantingXp; + } + + public double getHarvestXp() { + return harvestXp; + } + + public int getStartingState() { + return startingState; + } + + public int getEndingState() { + return endingState; + } + + public int getLimitState() { + return limitState; + } + + public int getStumpState() { + return stumpState; + } + + public int getCheckHealthState() { + return checkHealthState; + } + + public double getCheckHealthXp() { + return checkHealthExperience; + } + + public int getDiseaseDiffValue() { + return diseaseDiffValue; + } + + public int getDeathDiffValue() { + return deathDiffValue; + } + } + + /* This is the enum data about the different patches */ + + public enum FruitTreeFieldsData { + BRIMHAVEN(0, + new Point[] { new Point(2764, 3212), new Point(2765, 3213) }, + 2330), CATHERBY(1, new Point[] { new Point(2860, 3433), + new Point(2861, 3434) }, 2331), TREE_STRONGHOLD(2, new Point[] { + new Point(2475, 3445), new Point(2476, 3446) }, 2343), TREE_VILLAGE( + 3, + new Point[] { new Point(2489, 3179), new Point(2890, 3180) }, + 2344); + private int fruitTreeIndex; + private Point[] fruitTreePosition; + private int npcId; + + private static Map npcsProtecting = new HashMap(); + + static { + for (FruitTreeFieldsData data : FruitTreeFieldsData.values()) { + npcsProtecting.put(data.npcId, data); + + } + } + + public static FruitTreeFieldsData forId(int npcId) { + return npcsProtecting.get(npcId); + } + + FruitTreeFieldsData(int fruitTreeIndex, Point[] fruitTreePosition, + int npcId) { + this.fruitTreeIndex = fruitTreeIndex; + this.fruitTreePosition = fruitTreePosition; + this.npcId = npcId; + } + + public static FruitTreeFieldsData forIdPosition(int x, int y) { + for (FruitTreeFieldsData fruitTreeFieldsData : FruitTreeFieldsData + .values()) { + if (FarmingConstants.inRangeArea( + fruitTreeFieldsData.getFruitTreePosition()[0], + fruitTreeFieldsData.getFruitTreePosition()[1], x, y)) { + return fruitTreeFieldsData; + } + } + return null; + } + + public int getFruitTreeIndex() { + return fruitTreeIndex; + } + + public Point[] getFruitTreePosition() { + return fruitTreePosition; + } + + public int getNpcId() { + return npcId; + } + } + + /* This is the enum that hold the different data for inspecting the plant */ + + public enum InspectData { + + APPLE(5496, new String[][] { + { "The apple sapling has only just been planted." }, + { "The apple sapling grows into a small stump." }, + { "The apple stump grows a little larger." }, + { "The apple tree grows a small canopy." }, + { "The apple tree grows a second small canopy." }, + { "The apple tree grows larger." }, + { "The apple tree is ready to be harvested." }, }), BANANA( + 5497, + new String[][] { + { "The banana sapling has only just been planted." }, + { "The banana sapling grows 3 segments high, with 2 leaves." }, + { "The banana tree grows 2 more leaves." }, + { "The banana tree grows 5 segments high, and has some small bananas." }, + { "The banana tree grows a bit larger." }, + { "The banana tree grows a bit larger." }, + { "The banana tree is ready to be harvested." }, }), ORANGE( + 5498, + new String[][] { + { "The orange sapling has only just been planted." }, + { "The orange sapling grows slightly taller." }, + { "The orange sapling grows even taller." }, + { "The orange tree grows a small canopy." }, + { "The orange tree grows taller." }, + { "The orange tree grows wider and taller." }, + { "The oranges on the tree are ready to be harvested." } }), CURRY( + 5499, new String[][] { + { "The curry sapling has only just been planted." }, + { "The curry trunk grows towards the north." }, + { "The curry trunk grows towards the north." }, + { "The curry tree grows upwards." }, + { "The curry trunk grows towards the south." }, + { "The curry trunk grows towards the south." }, + { "The curry tree is ready to be harvested." } }), PINEAPPLE( + 5500, + new String[][] { + { "The pineapple sapling has only just been planted." }, + { "The pineapple plant grows larger." }, + { "The pineapple plant base turns brown." }, + { "The pineapple plant grows larger." }, + { "The pineapple plant grows larger." }, + { "The pineapple plant grows larger." }, + { "The pineapple plant is ready to be harvested." } }), PAPAYA( + 5501, new String[][] { + { "The papaya sapling has only just been planted." }, + { "The papaya sapling grows a little larger." }, + { "The papaya tree grows a little larger." }, + { "The papaya tree grows a bit larger." }, + { "The papaya tree grows some small yellow fruit." }, + { "The papaya tree grows larger." }, + { "The papaya tree is ready to be harvested." } }), PALM( + 5502, new String[][] { + { "The palm sapling has only just been planted." }, + { "The palm sapling grows a little larger." }, + { "The palm stump grows a little larger." }, + { "The palm tree grows a small canopy." }, + { "The palm tree grows taller." }, + { "The palm tree grows more leaves." }, + { "The palm tree is ready to be harvested." } }); + private int saplingId; + private String[][] messages; + + private static Map saplings = new HashMap(); + + static { + for (InspectData data : InspectData.values()) { + saplings.put(data.saplingId, data); + } + } + + InspectData(int saplingId, String[][] messages) { + this.saplingId = saplingId; + this.messages = messages; + } + + public static InspectData forId(int saplingId) { + return saplings.get(saplingId); + } + + public int getSapplingId() { + return saplingId; + } + + public String[][] getMessages() { + return messages; + } + } + + /* update all the patch states */ + + public void updateFruitTreeStates() { + // brimhaven - catherby - tree stronghold - tree village + int[] configValues = new int[fruitTreeStages.length]; + + int configValue; + for (int i = 0; i < fruitTreeStages.length; i++) { + configValues[i] = getConfigValue(fruitTreeStages[i], + fruitTreeSaplings[i], fruitTreeState[i], i); + } + // System.out.println("config 1 " + configValues[1]); + // System.out.println("config 0 " + configValues[0]); + configValue = (configValues[0] << 16) + (configValues[1] << 8 << 16) + + configValues[2] + (configValues[3] << 8); + player.getPacketSender().sendConfig(MAIN_FRUIT_TREE_CONFIG, configValue); + } + + /* getting the different config values */ + + public int getConfigValue(int fruitTreeStage, int saplingId, + int plantState, int index) { + FruitTreeData fruitTreeData = FruitTreeData.forId(saplingId); + switch (fruitTreeStage) { + case 0:// weed + return 0x00; + case 1:// weed cleared + return 0x01; + case 2: + return 0x02; + case 3: + return 0x03; + } + if (fruitTreeData == null) { + return -1; + } + if (fruitTreeStage > fruitTreeData.getEndingState() + - fruitTreeData.getStartingState() - 1) { + hasFullyGrown[index] = true; + } + + if (plantState == 6) + return fruitTreeData.getStumpState(); + + if (getPlantState(plantState, fruitTreeData, fruitTreeStage) == 3) + return fruitTreeData.getCheckHealthState(); + + return getPlantState(plantState, fruitTreeData, fruitTreeStage); + } + + /* getting the plant states */ + + public int getPlantState(int plantState, FruitTreeData fruitTreeData, + int fruitTreeStage) { + int value = fruitTreeData.getStartingState() + fruitTreeStage - 4; + switch (plantState) { + case 0: + return value; + case 1: + return value + fruitTreeData.getDiseaseDiffValue(); + case 2: + return value + fruitTreeData.getDeathDiffValue(); + case 3: + return fruitTreeData.getCheckHealthState(); + } + return -1; + } + + /* calculating the disease chance and making the plant grow */ + + public void doCalculations() { + for (int i = 0; i < fruitTreeSaplings.length; i++) { + if (fruitTreeStages[i] > 0 && fruitTreeStages[i] <= 3 + && GameEngine.getMinutesCounter() - fruitTreeTimer[i] >= 5) { + fruitTreeStages[i]--; + fruitTreeTimer[i] = GameEngine.getMinutesCounter(); + updateFruitTreeStates(); + continue; + } + FruitTreeData fruitTreeData = FruitTreeData + .forId(fruitTreeSaplings[i]); + if (fruitTreeData == null) { + continue; + } + + long difference = GameEngine.getMinutesCounter() + - fruitTreeTimer[i]; + long growth = fruitTreeData.getGrowthTime(); + int nbStates = fruitTreeData.getEndingState() + - fruitTreeData.getStartingState(); + int state = (int) (difference * nbStates / growth); + if (fruitTreeTimer[i] == 0 || fruitTreeState[i] == 2 + || fruitTreeState[i] == 3 || (state > nbStates)) { + continue; + } + if (4 + state != fruitTreeStages[i]) { + if (fruitTreeStages[i] + fruitTreeData.getStartingState() == fruitTreeData + .getLimitState() + 3) { + fruitTreeStages[i] = fruitTreeData.getEndingState() + - fruitTreeData.getStartingState() + 7; + fruitTreeState[i] = 3; + updateFruitTreeStates(); + continue; + } + fruitTreeStages[i] = 4 + state; + if (fruitTreeStages[i] <= 4 + state) + for (int j = fruitTreeStages[i]; j <= 4 + state; j++) + doStateCalculation(i); + updateFruitTreeStates(); + } + } + } + + /** + * Woodcutting action + * + * @param = tree id + * @param x + * = tree x location + * @param y + * = tree y location + * @return + */ + + public boolean cut(final int x, final int y) { + + final FruitTreeFieldsData fruitTreeFieldsData = FruitTreeFieldsData + .forIdPosition(x, y); + if (fruitTreeFieldsData == null) + return false; + final FruitTreeData fruitTreeData = FruitTreeData + .forId(fruitTreeSaplings[fruitTreeFieldsData + .getFruitTreeIndex()]); + if (fruitTreeData == null) + return false; + + if (player.getItemAssistant().freeSlots() <= 0) { + player.getPacketSender().sendMessage("Not enough space in your inventory."); + return true; + } + + if (ChopTree.getAxe(player) == null) { + return true; + } + player.getPacketSender().sendMessage("You swing your axe at the tree."); + final int emoteId = ChopTree.getAxe(player).getAnimation(); + player.startAnimation(emoteId); + + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender().sendMessage("You cut down the tree."); + fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] = 6; + updateFruitTreeStates(); + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(-1, 0); + + } + }, 5); + return true; + } + + public void modifyStage(int i) { + FruitTreeData fruitTreeData = FruitTreeData.forId(fruitTreeSaplings[i]); + if (fruitTreeData == null) + return; + long difference = GameEngine.getMinutesCounter() - fruitTreeTimer[i]; + long growth = fruitTreeData.getGrowthTime(); + int nbStates = fruitTreeData.getEndingState() + - fruitTreeData.getStartingState(); + int state = (int) (difference * nbStates / growth); + fruitTreeStages[i] = 4 + state; + updateFruitTreeStates(); + + } + + /* calculations about the diseasing chance */ + + public void doStateCalculation(int index) { + if (fruitTreeState[index] == 2) { + return; + } + // if the patch is diseased, it dies, if its watched by a farmer, it + // goes back to normal + if (fruitTreeState[index] == 1) { + if (fruitTreeWatched[index]) { + fruitTreeState[index] = 0; + FruitTreeData bushesData = FruitTreeData + .forId(fruitTreeSaplings[index]); + if (bushesData == null) + return; + System.out.println(fruitTreeSaplings[index]); + int difference = bushesData.getEndingState() + - bushesData.getStartingState(); + int growth = bushesData.getGrowthTime(); + fruitTreeTimer[index] += (growth / difference); + modifyStage(index); + } else { + fruitTreeState[index] = 2; + } + } + + if (fruitTreeState[index] == 5 && fruitTreeStages[index] != 2) { + fruitTreeState[index] = 0; + } + + if (fruitTreeState[index] == 0 && fruitTreeStages[index] >= 5 + && !hasFullyGrown[index]) { + FruitTreeData fruitTreeData = FruitTreeData + .forId(fruitTreeSaplings[index]); + if (fruitTreeData == null) { + return; + } + + double chance = diseaseChance[index] + * fruitTreeData.getDiseaseChance(); + int maxChance = (int) chance * 100; + if (Misc.random(100) <= maxChance) { + fruitTreeState[index] = 1; + } + } + } + + /* clearing the patch with a rake of a spade */ + + public boolean clearPatch(int objectX, int objectY, int itemId) { + final FruitTreeFieldsData fruitTreeFieldsData = FruitTreeFieldsData + .forIdPosition(objectX, objectY); + int finalAnimation; + int finalDelay; + if (fruitTreeFieldsData == null + || (itemId != FarmingConstants.RAKE && itemId != FarmingConstants.SPADE)) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] == 3) { + return true; + } + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] <= 3) { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a rake to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.RAKING_ANIM; + finalDelay = 5; + } + } else { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.SPADE_ANIM; + finalDelay = 3; + } + } + final int animation = finalAnimation; + player.stopPlayer(true); + player.startAnimation(animation); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.startAnimation(animation); + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] <= 2) { + fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()]++; + player.getItemAssistant().addItem(6055, 1); + } else { + fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] = 3; + container.stop(); + } + player.getPlayerAssistant().addSkillXP(CLEARING_EXPERIENCE, SkillConstants.FARMING.ordinal()); + fruitTreeTimer[fruitTreeFieldsData.getFruitTreeIndex()] = GameEngine + .getMinutesCounter(); + updateFruitTreeStates(); + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] == 3) { + container.stop(); + return; + } + } + + @Override + public void stop() { + resetFruitTrees(fruitTreeFieldsData.getFruitTreeIndex()); + player.getPacketSender().sendMessage("You clear the patch."); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, finalDelay); + return true; + + } + + /* planting the saplings */ + + public boolean plantSapling(int objectX, int objectY, final int saplingId) { + final FruitTreeFieldsData fruitTreeFieldsData = FruitTreeFieldsData + .forIdPosition(objectX, objectY); + final FruitTreeData fruitTreeData = FruitTreeData.forId(saplingId); + if (fruitTreeFieldsData == null || fruitTreeData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] != 3) { + player.getPacketSender().sendMessage("You can't plant a sapling here."); + return true; + } + if (fruitTreeData.getLevelRequired() > player.playerLevel[SkillConstants.FARMING.ordinal()]) { + player.getDialogueHandler().sendStatement( + "You need a farming level of " + + fruitTreeData.getLevelRequired() + + " to plant this sapling."); + return true; + } + + if (!player.getItemAssistant().playerHasItem(FarmingConstants.TROWEL)) { + player.getDialogueHandler().sendStatement( + "You need a trowel to plant the sapling here."); + return true; + } + player.startAnimation( + FarmingConstants.PLANTING_POT_ANIM); + fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] = 4; + player.getItemAssistant().removeItem(saplingId, 1); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] = 0; + fruitTreeSaplings[fruitTreeFieldsData.getFruitTreeIndex()] = saplingId; + fruitTreeTimer[fruitTreeFieldsData.getFruitTreeIndex()] = GameEngine + .getMinutesCounter(); + player.getPlayerAssistant().addSkillXP(fruitTreeData.getPlantingXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateFruitTreeStates(); + player.stopPlayer(false); + } + }, 3); + return true; + } + + /* harvesting the plant resulted */ + + public boolean harvestOrCheckHealth(int objectX, int objectY) { + final FruitTreeFieldsData fruitTreeFieldsData = FruitTreeFieldsData + .forIdPosition(objectX, objectY); + if (fruitTreeFieldsData == null) { + return false; + } + final FruitTreeData fruitTreeData = FruitTreeData + .forId(fruitTreeSaplings[fruitTreeFieldsData + .getFruitTreeIndex()]); + if (fruitTreeData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + System.out.println(fruitTreeStages[fruitTreeFieldsData + .getFruitTreeIndex()] + + fruitTreeData.getStartingState() + + " " + + (fruitTreeData.getLimitState() - 4)); + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] + + fruitTreeData.getStartingState() == fruitTreeData + .getLimitState() + 4) { + cut(objectX, objectY); + return true; + } + if (player.getItemAssistant().freeSlots() <= 0) { + player.getPacketSender().sendMessage("Not enough space in your inventory."); + return true; + } + player.startAnimation(832); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (player.getItemAssistant().freeSlots() <= 0) { + container.stop(); + return; + } + + if (fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] == 3) { + player.getPacketSender() + .sendMessage( + "You examine the tree for signs of disease and find that it's in perfect health."); + player.getPlayerAssistant().addSkillXP(fruitTreeData.getCheckHealthXp(), SkillConstants.FARMING.ordinal()); + fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] = 0; + hasFullyGrown[fruitTreeFieldsData.getFruitTreeIndex()] = false; + fruitTreeTimer[fruitTreeFieldsData.getFruitTreeIndex()] = GameEngine + .getMinutesCounter() + - fruitTreeData.getGrowthTime(); + modifyStage(fruitTreeFieldsData.getFruitTreeIndex()); + container.stop(); + return; + } + player.getPacketSender().sendMessage("You harvest the crop, and pick a fruit."); + player.getItemAssistant().addItem(fruitTreeData.getHarvestId(), 1); + player.getPlayerAssistant().addSkillXP(fruitTreeData.getHarvestXp(), SkillConstants.FARMING.ordinal()); + fruitTreeTimer[fruitTreeFieldsData.getFruitTreeIndex()] = GameEngine + .getMinutesCounter(); + int difference = fruitTreeData.getEndingState() + - fruitTreeData.getStartingState(); + int growth = fruitTreeData.getGrowthTime(); + lowerStage( + fruitTreeFieldsData.getFruitTreeIndex(), + growth + - (growth / difference) + * (difference + 5 - fruitTreeStages[fruitTreeFieldsData + .getFruitTreeIndex()])); + modifyStage(fruitTreeFieldsData.getFruitTreeIndex()); + container.stop(); + } + + @Override + public void stop() { + // TODO Auto-generated method stub + + } + }, 2); + return true; + } + + /* lowering the stage */ + + public void lowerStage(int index, int timer) { + hasFullyGrown[index] = false; + fruitTreeTimer[index] -= timer; + } + + /* putting compost onto the plant */ + + public boolean putCompost(int objectX, int objectY, final int itemId) { + if (itemId != 6032 && itemId != 6034) { + return false; + } + final FruitTreeFieldsData fruitTreeFieldsData = FruitTreeFieldsData + .forIdPosition(objectX, objectY); + if (fruitTreeFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] != 3 + || fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] == 5) { + player.getPacketSender().sendMessage("This patch doesn't need compost."); + return true; + } + player.getItemAssistant().removeItem(itemId, 1); + player.getItemAssistant().addItem(1925, 1); + + player.getPacketSender().sendMessage( + "You pour some " + (itemId == 6034 ? "super" : "") + + "compost on the patch."); + player.startAnimation(FarmingConstants.PUTTING_COMPOST); + player.getPlayerAssistant().addSkillXP(itemId == 6034 ? Compost.SUPER_COMPOST_EXP_USE : Compost.COMPOST_EXP_USE, SkillConstants.FARMING.ordinal()); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[fruitTreeFieldsData.getFruitTreeIndex()] *= itemId == 6032 ? COMPOST_CHANCE + : SUPERCOMPOST_CHANCE; + fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] = 5; + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + return true; + } + + /* inspecting a plant */ + + public boolean inspect(int objectX, int objectY) { + final FruitTreeFieldsData fruitTreeFieldsData = FruitTreeFieldsData + .forIdPosition(objectX, objectY); + if (fruitTreeFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + final InspectData inspectData = InspectData + .forId(fruitTreeSaplings[fruitTreeFieldsData + .getFruitTreeIndex()]); + final FruitTreeData fruitTreeData = FruitTreeData + .forId(fruitTreeSaplings[fruitTreeFieldsData + .getFruitTreeIndex()]); + if (fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] == 1) { + player.getDialogueHandler().sendStatement( + "This plant is diseased. Use a plant cure on it to cure it, ", + "or clear the patch with a spade."); + return true; + } else if (fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] == 2) { + player.getDialogueHandler().sendStatement( + "This plant is dead. You did not cure it while it was diseased.", + "Clear the patch with a spade."); + return true; + } else if (fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This plant has fully grown. You can check it's health", + "to gain some farming experiences."); + return true; + } else if (fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] == 6) { + player.getDialogueHandler().sendStatement( + "This is a fruit tree stump, to remove it, use a ", + "spade on it to clear the patch"); + return true; + } + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] == 0) { + player.getDialogueHandler().sendStatement("This is a fruit tree patch. The soil has not been treated.", + "The patch needs weeding."); + } else if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] == 3) { + player.getDialogueHandler().sendStatement("This is a fruit tree patch. The soil has not been treated.", + "The patch is empty and weeded."); + } else if (inspectData != null && fruitTreeData != null) { + player.getPacketSender().sendMessage( + "You bend down and start to inspect the patch..."); + + player.startAnimation(1331); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] - 4 < inspectData + .getMessages().length - 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[fruitTreeStages[fruitTreeFieldsData + .getFruitTreeIndex()] - 4]); + } else if (fruitTreeStages[fruitTreeFieldsData + .getFruitTreeIndex()] < fruitTreeData + .getEndingState() + - fruitTreeData.getStartingState() + 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 2]); + } else { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 1]); + } + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(1332); + player.stopPlayer(false); + // player.reset(); + } + }, 5); + } + return true; + } + + /* opening the corresponding guide about the patch */ + + public boolean guide(int objectX, int objectY) { + final FruitTreeFieldsData fruitTreeFieldsData = FruitTreeFieldsData + .forIdPosition(objectX, objectY); + if (fruitTreeFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + player.getSkillInterfaces().farmingComplex(4); + player.getSkillInterfaces().selected = 20; + return true; + } + + /* Curing the plant */ + + public boolean pruneArea(int objectX, int objectY, int itemId) { + final FruitTreeFieldsData fruitTreeFieldsData = FruitTreeFieldsData + .forIdPosition(objectX, objectY); + if (fruitTreeFieldsData == null + || (itemId != FarmingConstants.SECATEURS && itemId != FarmingConstants.MAGIC_SECATEURS)) { + return false; + } + final FruitTreeData fruitTreeData = FruitTreeData + .forId(fruitTreeSaplings[fruitTreeFieldsData + .getFruitTreeIndex()]); + if (fruitTreeData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] != 1) { + player.getPacketSender().sendMessage("This area doesn't need to be pruned."); + return true; + } + player.startAnimation(FarmingConstants.PRUNING_ANIM); + player.stopPlayer(true); + fruitTreeState[fruitTreeFieldsData.getFruitTreeIndex()] = 0; + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender().sendMessage( + "You prune the area with your secateurs."); + container.stop(); + } + + @Override + public void stop() { + updateFruitTreeStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 15); + + return true; + + } + + private void resetFruitTrees(int index) { + fruitTreeSaplings[index] = 0; + fruitTreeState[index] = 0; + diseaseChance[index] = 1; + hasFullyGrown[index] = false; + fruitTreeWatched[index] = false; + } + + /* checking if the patch is raked */ + + public boolean checkIfRaked(int objectX, int objectY) { + final FruitTreeFieldsData fruitTreeFieldsData = FruitTreeFieldsData + .forIdPosition(objectX, objectY); + if (fruitTreeFieldsData == null) + return false; + if (fruitTreeStages[fruitTreeFieldsData.getFruitTreeIndex()] == 3) + return true; + return false; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Herbs.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Herbs.java index b1c02633..223f96b3 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Herbs.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Herbs.java @@ -1,24 +1,835 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ package com.rebotted.game.content.skills.farming; +/** + * + * @author ArrowzFtw + */ +import java.awt.Point; +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; /** - * Herbs - * @author Andrew (Mr Extremez) + * Created by IntelliJ IDEA. User: vayken Date: 24/02/12 Time: 20:34 To change + * this template use File | Settings | File Templates. */ - public class Herbs { - - private static final int[] HERB_PATCH = {8150, 8151}; - - public static boolean isHerb(Player player, int objectType) { - for (int i = 0; i < HERB_PATCH.length; i++) { - if (objectType == HERB_PATCH[i]) { - return true; + + private Player player; + + // set of global constants for Farming + + private static final int START_HARVEST_AMOUNT = 3; + private static final int END_HARVEST_AMOUNT = 18; + + private static final double COMPOST_CHANCE = 0.9; + private static final double SUPERCOMPOST_CHANCE = 0.7; + private static final double CLEARING_EXPERIENCE = 4; + + public Herbs(Player player) { + this.player = player; + } + + // Farming data + public int[] herbStages = new int[4]; + public int[] herbSeeds = new int[4]; + public int[] herbHarvest = new int[4]; + public int[] herbState = new int[4]; + public long[] herbTimer = new long[4]; + public double[] diseaseChance = { 1, 1, 1, 1, 1 }; + + /* set of the constants for the patch */ + + // states - 2 bits plant - 6 bits + public static final int GROWING = 0x00; + + public static final int MAIN_HERB_LOCATION_CONFIG = 515; + + /* This is the enum holding the seeds info */ + + public enum HerbData { + GUAM(5291, 199, 9, 80, 0.25, 11, 12.5, 0x04, 0x08), MARRENTILL(5292, + 201, 14, 80, 0.25, 13.5, 15, 0x0b, 0x0f), TARROMIN(5293, 203, + 19, 80, 0.25, 16, 18, 0x12, 0x16), HARRALANDER(5294, 205, 26, + 80, 0.25, 21.5, 24, 0x19, 0x1d), GOUT_TUBER(6311, 3261, 29, 80, + 0.25, 105, 45, 0xc0, 0xc4), RANARR(5295, 207, 32, 80, 0.20, 27, + 30.5, 0x20, 0x24), TOADFLAX(5296, 3049, 38, 80, 0.20, 34, 38.5, + 0x27, 0x2b), IRIT(5297, 209, 44, 80, 0.20, 43, 48.5, 0x2e, 0x32), AVANTOE( + 5298, 211, 50, 80, 0.20, 54.5, 61.5, 0x35, 0x39), KUARM(5299, + 213, 56, 80, 0.20, 69, 78, 0x44, 0x48), SNAPDRAGON(5300, 3051, + 62, 80, 0.15, 87.5, 98.5, 0x4b, 0x4f), CADANTINE(5301, 215, 67, + 80, 0.15, 106.5, 120, 0x52, 0x56), LANTADYME(5302, 2485, 73, + 80, 0.15, 134.5, 151.5, 0x59, 0x5d), DWARF(5303, 217, 79, 80, + 0.15, 170.5, 192, 0x60, 0x64), TORSOL(5304, 219, 85, 80, 0.15, + 199.5, 224.5, 0x67, 0x6b) + + ; + + private int seedId; + private int harvestId; + private int levelRequired; + private int growthTime; + private double diseaseChance; + private double plantingXp; + private double harvestXp; + private int startingState; + private int endingState; + + private static Map seeds = new HashMap(); + + static { + for (HerbData data : HerbData.values()) { + seeds.put(data.seedId, data); } } + + HerbData(int seedId, int harvestId, int levelRequired, int growthTime, + double diseaseChance, double plantingXp, double harvestXp, + int startingState, int endingState) { + this.seedId = seedId; + this.harvestId = harvestId; + this.levelRequired = levelRequired; + this.growthTime = growthTime; + this.diseaseChance = diseaseChance; + this.plantingXp = plantingXp; + this.harvestXp = harvestXp; + this.startingState = startingState; + this.endingState = endingState; + } + + public static HerbData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public int getHarvestId() { + return harvestId; + } + + public int getLevelRequired() { + return levelRequired; + } + + public int getGrowthTime() { + return growthTime; + } + + public double getDiseaseChance() { + return diseaseChance; + } + + public double getPlantingXp() { + return plantingXp; + } + + public double getHarvestXp() { + return harvestXp; + } + + public int getStartingState() { + return startingState; + } + + public int getEndingState() { + return endingState; + } + } + + /* This is the enum data about the different patches */ + + public enum HerbFieldsData { + ARDOUGNE(0, + new Point[] { new Point(2670, 3374), new Point(2671, 3375) }), PHASMATYS( + 1, new Point[] { new Point(3605, 3529), new Point(3606, 3530) }), FALADOR( + 2, new Point[] { new Point(3058, 3311), new Point(3059, 3312) }), CATHERBY( + 3, new Point[] { new Point(2813, 3463), new Point(2814, 3464) }); + private int herbIndex; + private Point[] herbPosition; + + HerbFieldsData(int herbIndex, Point[] herbPosition) { + this.herbIndex = herbIndex; + this.herbPosition = herbPosition; + } + + public static HerbFieldsData forIdPosition(int x, int y) { + for (HerbFieldsData herbFieldsData : HerbFieldsData.values()) { + if (FarmingConstants.inRangeArea( + herbFieldsData.getHerbPosition()[0], + herbFieldsData.getHerbPosition()[1], x, y)) { + return herbFieldsData; + } + } + return null; + } + + public int getHerbIndex() { + return herbIndex; + } + + public Point[] getHerbPosition() { + return herbPosition; + } + } + + /* This is the enum that hold the different data for inspecting the plant */ + + public enum InspectData { + + GUAM(5291, new String[][] { { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), MARRENTILL( + 5292, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), TARROMIN( + 5293, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), HARRALANDER( + 5294, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), GOUT_TUBER( + 6311, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), RANARR( + 5295, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), TOADFLAX( + 5296, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), IRIT( + 5297, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), AVANTOE( + 5298, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), KUARM( + 5299, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), SNAPDRAGON( + 5300, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), CADANTINE( + 5301, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), LANTADYME( + 5302, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), DWARF( + 5303, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }), TORSOL( + 5304, new String[][] { + { "The seed has only just been planted." }, + { "The herb is now ankle height." }, + { "The herb is now knee height." }, + { "The herb is now mid-thigh height." }, + { "The herb is fully grown and ready to harvest." } }) + + ; + private int seedId; + private String[][] messages; + + private static Map seeds = new HashMap(); + + static { + for (InspectData data : InspectData.values()) { + seeds.put(data.seedId, data); + } + } + + InspectData(int seedId, String[][] messages) { + this.seedId = seedId; + this.messages = messages; + } + + public static InspectData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public String[][] getMessages() { + return messages; + } + } + + /* update all the patch states */ + + public void updateHerbsStates() { + // falador catherby ardougne phasmatys + int[] configValues = new int[herbStages.length]; + + int configValue; + for (int i = 0; i < herbStages.length; i++) { + configValues[i] = getConfigValue(herbStages[i], herbSeeds[i], + herbState[i], i); + } + + configValue = (configValues[0] << 16) + (configValues[1] << 8 << 16) + + configValues[2] + (configValues[3] << 8); + player.getPacketSender().sendConfig(MAIN_HERB_LOCATION_CONFIG, configValue); + + } + + /* getting the different config values */ + + public int getConfigValue(int herbStage, int seedId, int plantState, + int index) { + HerbData herbData = HerbData.forId(seedId); + switch (herbStage) { + case 0:// weed + return (GROWING << 6) + 0x00; + case 1:// weed cleared + return (GROWING << 6) + 0x01; + case 2: + return (GROWING << 6) + 0x02; + case 3: + return (GROWING << 6) + 0x03; + } + if (herbData == null) { + return -1; + } + if (herbSeeds[index] == 6311) { + if (plantState == 1) { + return herbStages[index] + 0xc1; + } else if (plantState == 2) { + return herbStages[index] + 0xc3; + } + } + return (plantState == 2 ? herbStages[index] + 0x9e + : plantState == 1 ? herbStages[index] + 0x9a + : getPlantState(plantState) << 6) + + herbData.getStartingState() + herbStage - 4; + } + + /* getting the plant states */ + + public int getPlantState(int plantState) { + switch (plantState) { + case 0: + return GROWING; + } + return -1; + } + + /* calculating the disease chance and making the plant grow */ + + public void doCalculations() { + for (int i = 0; i < herbSeeds.length; i++) { + if (herbStages[i] > 0 && herbStages[i] <= 3 + && GameEngine.getMinutesCounter() - herbTimer[i] >= 5) { + herbStages[i]--; + herbTimer[i] = GameEngine.getMinutesCounter(); + updateHerbsStates(); + } + HerbData herbData = HerbData.forId(herbSeeds[i]); + if (herbData == null) { + continue; + } + + long difference = GameEngine.getMinutesCounter() - herbTimer[i]; + long growth = herbData.getGrowthTime(); + int nbStates = herbData.getEndingState() + - herbData.getStartingState(); + int state = (int) (difference * nbStates / growth); + if (herbTimer[i] == 0 || herbState[i] == 2 || state > nbStates) { + continue; + } + if (4 + state != herbStages[i]) { + herbStages[i] = 4 + state; + doStateCalculation(i); + updateHerbsStates(); + } + } + } + + /* calculations about the diseasing chance */ + + public void doStateCalculation(int index) { + if (herbState[index] == 2) { + return; + } + // if the patch is diseased, it dies, if its watched by a farmer, it + // goes back to normal + if (herbState[index] == 1) { + herbState[index] = 2; + } + + if (herbState[index] == 4 && herbStages[index] != 3) { + herbState[index] = 0; + } + + if (herbState[index] == 0 && herbStages[index] >= 4 + && herbStages[index] <= 7) { + HerbData herbData = HerbData.forId(herbSeeds[index]); + if (herbData == null) { + return; + } + double chance = diseaseChance[index] * herbData.getDiseaseChance(); + int maxChance = (int) chance * 100; + if (Misc.random(100) <= maxChance) { + herbState[index] = 1; + } + } + } + + /* clearing the patch with a rake of a spade */ + + public boolean clearPatch(int objectX, int objectY, int itemId) { + final HerbFieldsData herbFieldsData = HerbFieldsData.forIdPosition( + objectX, objectY); + int finalAnimation; + int finalDelay; + if (herbFieldsData == null + || (itemId != FarmingConstants.RAKE && itemId != FarmingConstants.SPADE)) { + return false; + } + if (herbStages[herbFieldsData.getHerbIndex()] == 3) { + return true; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (herbStages[herbFieldsData.getHerbIndex()] <= 3) { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a rake to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.RAKING_ANIM; + finalDelay = 5; + } + } else { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.SPADE_ANIM; + finalDelay = 3; + } + } + final int animation = finalAnimation; + player.stopPlayer(true); + player.startAnimation(animation); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.startAnimation(animation); + if (herbStages[herbFieldsData.getHerbIndex()] <= 2) { + herbStages[herbFieldsData.getHerbIndex()]++; + player.getItemAssistant().addItem(6055, 1); + } else { + herbStages[herbFieldsData.getHerbIndex()] = 3; + container.stop(); + } + player.getPlayerAssistant().addSkillXP(CLEARING_EXPERIENCE, SkillConstants.FARMING.ordinal()); + herbTimer[herbFieldsData.getHerbIndex()] = GameEngine + .getMinutesCounter(); + updateHerbsStates(); + if (herbStages[herbFieldsData.getHerbIndex()] == 3) { + container.stop(); + return; + } + } + + @Override + public void stop() { + resetHerbs(herbFieldsData.getHerbIndex()); + player.getPacketSender().sendMessage("You clear the patch."); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, finalDelay); + return true; + + } + + /* planting the seeds */ + + public boolean plantSeed(int objectX, int objectY, final int seedId) { + final HerbFieldsData herbFieldsData = HerbFieldsData.forIdPosition( + objectX, objectY); + final HerbData herbData = HerbData.forId(seedId); + if (herbFieldsData == null || herbData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (herbStages[herbFieldsData.getHerbIndex()] != 3) { + player.getPacketSender().sendMessage("You can't plant a seed here."); + return false; + } + if (herbData.getLevelRequired() > player.playerLevel[SkillConstants.FARMING.ordinal()]) { + player.getDialogueHandler().sendStatement("You need a farming level of " + + herbData.getLevelRequired() + + " to plant this seed."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SEED_DIBBER)) { + player.getDialogueHandler().sendStatement( + "You need a seed dibber to plant seed here."); + return true; + } + player.startAnimation(FarmingConstants.SEED_DIBBING); + player.getItemAssistant().deleteItem(seedId, 1); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + herbState[herbFieldsData.getHerbIndex()] = 0; + herbStages[herbFieldsData.getHerbIndex()] = 4; + herbSeeds[herbFieldsData.getHerbIndex()] = seedId; + herbTimer[herbFieldsData.getHerbIndex()] = GameEngine + .getMinutesCounter(); + player.getPlayerAssistant().addSkillXP(herbData.getPlantingXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateHerbsStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 3); + return true; + } + + /* harvesting the plant resulted */ + + public boolean harvest(int objectX, int objectY) { + final HerbFieldsData herbFieldsData = HerbFieldsData.forIdPosition( + objectX, objectY); + if (herbFieldsData == null) { + return false; + } + final HerbData herbData = HerbData.forId(herbSeeds[herbFieldsData + .getHerbIndex()]); + if (herbData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to harvest here."); + return true; + } + + player.startAnimation( + FarmingConstants.PICKING_VEGETABLE_ANIM); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (herbHarvest[herbFieldsData.getHerbIndex()] == 0) { + herbHarvest[herbFieldsData.getHerbIndex()] = 1 + (START_HARVEST_AMOUNT + Misc + .random(END_HARVEST_AMOUNT - START_HARVEST_AMOUNT)) * (1); + } + + if (herbHarvest[herbFieldsData.getHerbIndex()] == 1) { + resetHerbs(herbFieldsData.getHerbIndex()); + herbStages[herbFieldsData.getHerbIndex()] = 3; + herbTimer[herbFieldsData.getHerbIndex()] = GameEngine + .getMinutesCounter(); + container.stop(); + return; + } + if (player.getItemAssistant().freeSlots() <= 0) { + container.stop(); + return; + } + herbHarvest[herbFieldsData.getHerbIndex()]--; + player.startAnimation( + FarmingConstants.PICKING_HERB_ANIM); + player.getPacketSender().sendMessage( + "You harvest the crop, and get some herbs."); + player.getItemAssistant().addItem(herbData.getHarvestId(), 1); + player.getPlayerAssistant().addSkillXP(herbData.getHarvestXp(), SkillConstants.FARMING.ordinal()); + } + + @Override + public void stop() { + updateHerbsStates(); + player.getPlayerAssistant().resetAnimation(); + } + }, 3); + return true; + } + + /* putting compost onto the plant */ + + public boolean putCompost(int objectX, int objectY, final int itemId) { + if (itemId != 6032 && itemId != 6034) { + return false; + } + final HerbFieldsData herbFieldsData = HerbFieldsData.forIdPosition( + objectX, objectY); + if (herbFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (herbStages[herbFieldsData.getHerbIndex()] != 3 + || herbState[herbFieldsData.getHerbIndex()] == 4) { + player.getPacketSender().sendMessage("This patch doesn't need compost."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(1925, 1); + + player.getPacketSender().sendMessage( + "You pour some " + (itemId == 6034 ? "super" : "") + + "compost on the patch."); + player.startAnimation(FarmingConstants.PUTTING_COMPOST); + player.getPlayerAssistant().addSkillXP(itemId == 6034 ? Compost.SUPER_COMPOST_EXP_USE + : Compost.COMPOST_EXP_USE, SkillConstants.FARMING.ordinal()); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[herbFieldsData.getHerbIndex()] *= itemId == 6032 ? COMPOST_CHANCE + : SUPERCOMPOST_CHANCE; + herbState[herbFieldsData.getHerbIndex()] = 4; + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + return true; + } + + /* inspecting a plant */ + + public boolean inspect(int objectX, int objectY) { + final HerbFieldsData herbFieldsData = HerbFieldsData.forIdPosition( + objectX, objectY); + if (herbFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + final InspectData inspectData = InspectData + .forId(herbSeeds[herbFieldsData.getHerbIndex()]); + final HerbData herbData = HerbData.forId(herbSeeds[herbFieldsData + .getHerbIndex()]); + if (herbState[herbFieldsData.getHerbIndex()] == 1) { + player.getDialogueHandler().sendStatement("This plant is diseased. Use a plant cure on it to cure it, ", + "or clear the patch with a spade."); + return true; + } else if (herbState[herbFieldsData.getHerbIndex()] == 2) { + player.getDialogueHandler().sendStatement("This plant is dead. You did not cure it while it was diseased.", + "Clear the patch with a spade."); + return true; + } + if (herbStages[herbFieldsData.getHerbIndex()] == 0) { + player.getDialogueHandler().sendStatement( + "This is an herb patch. The soil has not been treated.", + "The patch needs weeding."); + } else if (herbStages[herbFieldsData.getHerbIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This is an herb patch. The soil has not been treated.", + "The patch is empty and weeded."); + } else if (inspectData != null && herbData != null) { + player.getPacketSender().sendMessage( + "You bend down and start to inspect the patch..."); + + player.startAnimation(1331); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (herbStages[herbFieldsData.getHerbIndex()] - 4 < inspectData + .getMessages().length - 2) { + player.getDialogueHandler().sendStatement( inspectData + .getMessages()[herbStages[herbFieldsData + .getHerbIndex()] - 4]); + } else if (herbStages[herbFieldsData.getHerbIndex()] < herbData + .getEndingState() - herbData.getStartingState() + 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 2]); + } else { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 1]); + } + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(1332); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 5); + } + return true; + } + + /* opening the corresponding guide about the patch */ + + public boolean guide(int objectX, int objectY) { + final HerbFieldsData herbFieldsData = HerbFieldsData.forIdPosition( + objectX, objectY); + if (herbFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + player.getSkillInterfaces().farmingComplex(7); + player.getSkillInterfaces().selected = 20; + return true; + } + + /* Curing the plant */ + + public boolean curePlant(int objectX, int objectY, int itemId) { + final HerbFieldsData herbFieldsData = HerbFieldsData.forIdPosition( + objectX, objectY); + if (herbFieldsData == null || itemId != 6036) { + return false; + } + final HerbData herbData = HerbData.forId(herbSeeds[herbFieldsData + .getHerbIndex()]); + if (herbData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (herbState[herbFieldsData.getHerbIndex()] != 1) { + player.getPacketSender().sendMessage("This plant doesn't need to be cured."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(229, 1); + player.startAnimation(FarmingConstants.CURING_ANIM); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender().sendMessage( + "You cure the plant with a plant cure."); + herbState[herbFieldsData.getHerbIndex()] = 0; + container.stop(); + } + + @Override + public void stop() { + updateHerbsStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + + return true; + + } + + @SuppressWarnings("unused") + private void resetHerbs() { + for (int i = 0; i < herbStages.length; i++) { + herbSeeds[i] = 0; + herbState[i] = 0; + diseaseChance[i] = 0; + herbHarvest[i] = 0; + } + } + + /* reseting the patches */ + + private void resetHerbs(int index) { + herbSeeds[index] = 0; + herbState[index] = 0; + diseaseChance[index] = 1; + herbHarvest[index] = 0; + } + + /* checking if the patch is raked */ + + public boolean checkIfRaked(int objectX, int objectY) { + final HerbFieldsData herbFieldsData = HerbFieldsData.forIdPosition( + objectX, objectY); + if (herbFieldsData == null) + return false; + if (herbStages[herbFieldsData.getHerbIndex()] == 3) + return true; return false; - } } diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Hops.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Hops.java new file mode 100644 index 00000000..5d283ded --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Hops.java @@ -0,0 +1,933 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.rebotted.game.content.skills.farming; + +/** + * + * @author ArrowzFtw + */ + +import java.awt.Point; +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; +/** + * Created by IntelliJ IDEA. User: vayken Date: 24/02/12 Time: 20:34 To change + * this template use File | Settings | File Templates. + */ +public class Hops { + + private Player player; + + // set of global constants for Farming + + private static final int START_HARVEST_AMOUNT = 3; + private static final int END_HARVEST_AMOUNT = 41; + + private static final double WATERING_CHANCE = 0.5; + private static final double COMPOST_CHANCE = 0.9; + private static final double SUPERCOMPOST_CHANCE = 0.7; + private static final double CLEARING_EXPERIENCE = 4; + + public Hops(Player player) { + this.player = player; + } + + // Farming data + public int[] hopsStages = new int[4]; + public int[] hopsSeeds = new int[4]; + public int[] hopsHarvest = new int[4]; + public int[] hopsState = new int[4]; + public long[] hopsTimer = new long[4]; + public double[] diseaseChance = { 1, 1, 1, 1 }; + public boolean[] hasFullyGrown = { false, false, false, false }; + public boolean[] hopsWatched = { false, false, false, false }; + + /* set of the constants for the patch */ + + // states - 2 bits plant - 6 bits + public static final int GROWING = 0x00; + public static final int WATERED = 0x01; + public static final int DISEASED = 0x02; + public static final int DEAD = 0x03; + + public static final int MAIN_HOPS_CONFIG = 506; + + /* This is the enum holding the seeds info */ + + public enum HopsData { + BARLEY(5305, 6006, 4, 3, new int[] { 6032, 3 }, 40, 0.35, 8.5, 9.5, + 0x31, 0x35), HAMMERSTONE(5307, 5994, 4, 4, + new int[] { 6010, 1 }, 40, 0.35, 9, 10, 0x04, 0x08), ASGARNIAN( + 5308, 5996, 4, 8, new int[] { 5458, 1 }, 40, 0.30, 10.5, 12, + 0x0b, 0x10), JUTE(5306, 5931, 3, 13, new int[] { 6008, 6 }, 40, + 0.30, 13, 14.5, 0x38, 0x3d), YANILLIAN(5309, 5998, 4, 16, + new int[] { 5968, 1 }, 40, 0.25, 14.5, 16, 0x13, 0x19), KRANDORIAN( + 5310, 6000, 4, 21, new int[] { 5478 }, 40, 0.25, 17.5, 19.5, + 0x1c, 0x23), WILDBLOOD(5311, 6002, 4, 28, + new int[] { 6012, 1 }, 40, 0.20, 23, 26, 0x26, 0x2e), ; + + private int seedId; + private int harvestId; + private int seedAmount; + private int levelRequired; + private int[] paymentToWatch; + private int growthTime; + private double diseaseChance; + private double plantingXp; + private double harvestXp; + private int startingState; + private int endingState; + + private static Map seeds = new HashMap(); + + static { + for (HopsData data : HopsData.values()) { + seeds.put(data.seedId, data); + } + } + + HopsData(int seedId, int harvestId, int seedAmount, int levelRequired, + int[] paymentToWatch, int growthTime, double diseaseChance, + double plantingXp, double harvestXp, int startingState, + int endingState) { + this.seedId = seedId; + this.harvestId = harvestId; + this.seedAmount = seedAmount; + this.levelRequired = levelRequired; + this.paymentToWatch = paymentToWatch; + this.growthTime = growthTime; + this.diseaseChance = diseaseChance; + this.plantingXp = plantingXp; + this.harvestXp = harvestXp; + this.startingState = startingState; + this.endingState = endingState; + } + + public static HopsData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public int getHarvestId() { + return harvestId; + } + + public int getSeedAmount() { + return seedAmount; + } + + public int getLevelRequired() { + return levelRequired; + } + + public int[] getPaymentToWatch() { + return paymentToWatch; + } + + public int getGrowthTime() { + return growthTime; + } + + public double getDiseaseChance() { + return diseaseChance; + } + + public double getPlantingXp() { + return plantingXp; + } + + public double getHarvestXp() { + return harvestXp; + } + + public int getStartingState() { + return startingState; + } + + public int getEndingState() { + return endingState; + } + } + + /* This is the enum data about the different patches */ + + public enum HopsFieldsData { + + LUMBRIDGE(0, + new Point[] { new Point(3227, 3313), new Point(3231, 3317) }, + 2333), MCGRUBOR(1, new Point[] { new Point(2664, 3523), + new Point(2669, 3528) }, 2334), YANILLE(2, new Point[] { + new Point(2574, 3103), new Point(2577, 3106) }, 2332), ENTRANA( + 3, + new Point[] { new Point(2809, 3335), new Point(2812, 3338) }, + 2327); + + private int hopsIndex; + private Point[] hopsPosition; + private int npcId; + + private static Map npcsProtecting = new HashMap(); + + static { + for (HopsFieldsData data : HopsFieldsData.values()) { + npcsProtecting.put(data.npcId, data); + + } + } + + public static HopsFieldsData forId(int npcId) { + return npcsProtecting.get(npcId); + } + + HopsFieldsData(int hopsIndex, Point[] hopsPosition, int npcId) { + this.hopsIndex = hopsIndex; + this.hopsPosition = hopsPosition; + this.npcId = npcId; + } + + public static HopsFieldsData forIdPosition(int x, int y) { + for (HopsFieldsData hopsFieldsData : HopsFieldsData.values()) { + if (FarmingConstants.inRangeArea( + hopsFieldsData.getHopsPosition()[0], + hopsFieldsData.getHopsPosition()[1], x, y)) { + return hopsFieldsData; + } + } + return null; + } + + public int getHopsIndex() { + return hopsIndex; + } + + public Point[] getHopsPosition() { + return hopsPosition; + } + + public int getNpcId() { + return npcId; + } + } + + /* This is the enum that hold the different data for inspecting the plant */ + + public enum InspectData { + + BARLEY(5305, new String[][] { + { "The barley seeds have only just been planted." }, + { "Grain heads develop at the upper part of the stalks,", + "as the barley grows taller." }, + { "The barley grows taller, the heads weighing", + "slightly on the stalks." }, + { "The barley grows taller." }, + { "The barley is ready to harvest. The heads of grain", + "are weighing down heavily on the stalks!" } }), HAMMERSTONE( + 5307, + new String[][] { + { "The Hammerstone seeds have only just been planted." }, + { "The Hammerstone hops plant grows a little bit taller." }, + { "The Hammerstone hops plant grows a bit taller." }, + { "The Hammerstone hops plant grows a bit taller." }, + { "The Hammerstone hops plant is ready to harvest." } }), ASGARNIAN( + 5308, new String[][] { + { "The Asgarnian seeds have only just been planted." }, + { "The Asgarnian hops plant grows a bit taller." }, + { "The Asgarnian hops plant grows a bit taller." }, + { "The Asgarnian hops plant grows a bit taller." }, + { "The upper new leaves appear dark green to the", + "rest of the plant." }, + { "The Asgarnian hops plant is ready to harvest." } }), JUTE( + 5306, new String[][] { + { "The Jute seeds have only just been planted." }, + { "The jute plants grow taller." }, + { "The jute plants grow taller." }, + { "The jute plants grow taller." }, + { "The jute plant grows taller. They are as high", + "as the player." }, + { "The jute plants are ready to harvest." } }), YANILLIAN( + 5309, new String[][] { + { "The Yanillian seeds have only just been planted." }, + { "The Yanillian hops plant grows a bit taller." }, + { "The Yanillian hops plant grows a bit taller." }, + { "The Yanillian hops plant grows a bit taller." }, + { "The new leaves on the top of the Yanillian hops", + "plant are dark green." }, + { "The new leaves on the top of the Yanillian hops", + "plant are dark green." }, + { "The Yanillian hops plant is ready to harvest." } }), KRANDORIAN( + 5310, + new String[][] { + { "The Krandorian seeds have only just been planted." }, + { "The Krandorian plant grows a bit taller." }, + { "The Krandorian plant grows a bit taller." }, + { "The Krandorian plant grows a bit taller." }, + { "The new leaves on top of the Krandorian plant are", + "dark green." }, + { "The Krandorian plant grows a bit taller." }, + { "The new leaves on top of the Krandorian plant", + "are dark green." }, + { "The Krandorian plant is ready for harvesting." } }), WILDBLOOD( + 5311, + new String[][] { + { "The wildblood seeds have only just been planted." }, + { "The wildblood hops plant grows a bit taller." }, + { "The wildblood hops plant grows a bit taller." }, + { "The wildblood hops plant grows a bit taller." }, + { "The wildblood hops plant grows a bit taller." }, + { "The wildblood hops plant grows a bit taller." }, + { "The wildblood hops plant grows a bit taller." }, + { + "The new leaves at the top of the wildblood hops plant", + "are dark green." }, + { "The wildblood hops plant is ready to harvest." } }); + private int seedId; + private String[][] messages; + + private static Map seeds = new HashMap(); + + static { + for (InspectData data : InspectData.values()) { + seeds.put(data.seedId, data); + } + } + + InspectData(int seedId, String[][] messages) { + this.seedId = seedId; + this.messages = messages; + } + + public static InspectData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public String[][] getMessages() { + return messages; + } + } + + /* update all the patch states */ + + public void updateHopsStates() { + // lumbridge - mc grubor - yanille - entrana + int[] configValues = new int[hopsStages.length]; + + int configValue; + for (int i = 0; i < hopsStages.length; i++) { + configValues[i] = getConfigValue(hopsStages[i], hopsSeeds[i], + hopsState[i], i); + } + + configValue = (configValues[0] << 16) + (configValues[1] << 8 << 16) + + configValues[2] + (configValues[3] << 8); + player.getPacketSender().sendConfig(MAIN_HOPS_CONFIG, configValue); + + } + + /* getting the different config values */ + + public int getConfigValue(int hopsStage, int seedId, int plantState, + int index) { + HopsData hopsData = HopsData.forId(seedId); + switch (hopsStage) { + case 0:// weed + return (GROWING << 6) + 0x00; + case 1:// weed cleared + return (GROWING << 6) + 0x01; + case 2: + return (GROWING << 6) + 0x02; + case 3: + return (GROWING << 6) + 0x03; + } + if (hopsData == null) { + return -1; + } + if (hopsData.getEndingState() == hopsData.getStartingState() + + hopsStage - 1) { + hasFullyGrown[index] = true; + } + + return (getPlantState(plantState) << 6) + hopsData.getStartingState() + + hopsStage - 4; + } + + /* getting the plant states */ + + public int getPlantState(int plantState) { + switch (plantState) { + case 0: + return GROWING; + case 1: + return WATERED; + case 2: + return DISEASED; + case 3: + return DEAD; + } + return -1; + } + + /* calculating the disease chance and making the plant grow */ + + public void doCalculations() { + for (int i = 0; i < hopsSeeds.length; i++) { + if (hopsStages[i] > 0 && hopsStages[i] <= 3 + && GameEngine.getMinutesCounter() - hopsTimer[i] >= 5) { + hopsStages[i]--; + hopsTimer[i] = GameEngine.getMinutesCounter(); + updateHopsStates(); + continue; + } + HopsData hopsData = HopsData.forId(hopsSeeds[i]); + if (hopsData == null) { + continue; + } + + long difference = GameEngine.getMinutesCounter() - hopsTimer[i]; + long growth = hopsData.getGrowthTime(); + int nbStates = hopsData.getEndingState() + - hopsData.getStartingState(); + int state = (int) (difference * nbStates / growth); + if (hopsTimer[i] == 0 || hopsState[i] == 3 || state > nbStates) { + continue; + } + if (4 + state != hopsStages[i]) { + hopsStages[i] = 4 + state; + if (hopsStages[i] <= 4 + state) + for (int j = hopsStages[i]; j <= 4 + state; j++) + doStateCalculation(i); + updateHopsStates(); + } + } + } + + public void modifyStage(int i) { + HopsData hopsData = HopsData.forId(hopsSeeds[i]); + if (hopsData == null) + return; + long difference = GameEngine.getMinutesCounter() - hopsTimer[i]; + long growth = hopsData.getGrowthTime(); + int nbStates = hopsData.getEndingState() - hopsData.getStartingState(); + int state = (int) (difference * nbStates / growth); + hopsStages[i] = 4 + state; + updateHopsStates(); + + } + + /* calculations about the diseasing chance */ + + public void doStateCalculation(int index) { + if (hopsState[index] == 3) { + return; + } + // if the patch is diseased, it dies, if its watched by a farmer, it + // goes back to normal + if (hopsState[index] == 2) { + if (hopsWatched[index]) { + hopsState[index] = 0; + HopsData hopsData = HopsData.forId(hopsSeeds[index]); + if (hopsData == null) + return; + int difference = hopsData.getEndingState() + - hopsData.getStartingState(); + int growth = hopsData.getGrowthTime(); + hopsTimer[index] += (growth / difference); + modifyStage(index); + } else { + hopsState[index] = 3; + } + } + + if (hopsState[index] == 1) { + diseaseChance[index] *= 2; + hopsState[index] = 0; + } + + if (hopsState[index] == 5 && hopsStages[index] != 3) { + hopsState[index] = 0; + } + + if (hopsState[index] == 0 && hopsStages[index] >= 5 + && !hasFullyGrown[index]) { + HopsData hopsData = HopsData.forId(hopsSeeds[index]); + if (hopsData == null) { + return; + } + + double chance = diseaseChance[index] * hopsData.getDiseaseChance(); + int maxChance = (int) chance * 100; + if (Misc.random(100) <= maxChance) { + hopsState[index] = 2; + } + } + } + + /* watering the patch */ + + public boolean waterPatch(int objectX, int objectY, int itemId) { + final HopsFieldsData hopsFieldsData = HopsFieldsData.forIdPosition( + objectX, objectY); + if (hopsFieldsData == null) { + return false; + } + HopsData hopsData = HopsData.forId(hopsSeeds[hopsFieldsData + .getHopsIndex()]); + if (hopsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (hopsState[hopsFieldsData.getHopsIndex()] == 1 + || hopsStages[hopsFieldsData.getHopsIndex()] <= 1 + || hopsStages[hopsFieldsData.getHopsIndex()] == hopsData + .getEndingState() - hopsData.getStartingState() + 4) { + player.getPacketSender().sendMessage("This patch doesn't need watering."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(itemId == 5333 ? itemId - 2 : itemId - 1, 1); + + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a seed dibber to plant seed here."); + return true; + } + player.getPacketSender().sendMessage("You water the patch."); + player.startAnimation( + FarmingConstants.WATERING_CAN_ANIM); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[hopsFieldsData.getHopsIndex()] *= WATERING_CHANCE; + hopsState[hopsFieldsData.getHopsIndex()] = 1; + container.stop(); + } + + @Override + public void stop() { + updateHopsStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 5); + return true; + } + + /* clearing the patch with a rake of a spade */ + + public boolean clearPatch(int objectX, int objectY, int itemId) { + final HopsFieldsData hopsFieldsData = HopsFieldsData.forIdPosition( + objectX, objectY); + int finalAnimation; + int finalDelay; + if (hopsFieldsData == null + || (itemId != FarmingConstants.RAKE && itemId != FarmingConstants.SPADE)) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (hopsStages[hopsFieldsData.getHopsIndex()] == 3) { + return true; + } + if (hopsStages[hopsFieldsData.getHopsIndex()] <= 3) { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a rake to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.RAKING_ANIM; + finalDelay = 5; + } + } else { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.SPADE_ANIM; + finalDelay = 3; + } + } + final int animation = finalAnimation; + player.stopPlayer(true); + player.startAnimation(animation); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.startAnimation(animation); + if (hopsStages[hopsFieldsData.getHopsIndex()] <= 2) { + hopsStages[hopsFieldsData.getHopsIndex()]++; + player.getItemAssistant().addItem(6055, 1); + } else { + hopsStages[hopsFieldsData.getHopsIndex()] = 3; + container.stop(); + } + player.getPlayerAssistant().addSkillXP(CLEARING_EXPERIENCE, SkillConstants.FARMING.ordinal()); + hopsTimer[hopsFieldsData.getHopsIndex()] = GameEngine + .getMinutesCounter(); + updateHopsStates(); + if (hopsStages[hopsFieldsData.getHopsIndex()] == 3) { + container.stop(); + return; + } + } + + @Override + public void stop() { + resetHops(hopsFieldsData.getHopsIndex()); + player.getPacketSender().sendMessage("You clear the patch."); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, finalDelay); + return true; + + } + + /* planting the seeds */ + + public boolean plantSeed(int objectX, int objectY, final int seedId) { + final HopsFieldsData hopsFieldsData = HopsFieldsData.forIdPosition( + objectX, objectY); + final HopsData hopsData = HopsData.forId(seedId); + if (hopsFieldsData == null || hopsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (hopsStages[hopsFieldsData.getHopsIndex()] != 3) { + player.getPacketSender().sendMessage("You can't plant a seed here."); + return false; + } + if (hopsData.getLevelRequired() > player.playerLevel[SkillConstants.FARMING.ordinal()]) { + player.getDialogueHandler().sendStatement("You need a farming level of " + + hopsData.getLevelRequired() + + " to plant this seed."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SEED_DIBBER)) { + player.getDialogueHandler().sendStatement( + "You need a seed dibber to plant seed here."); + return true; + } + if (player.getItemAssistant().getItemAmount(hopsData.getSeedId()) < hopsData + .getSeedAmount()) { + player.getDialogueHandler().sendStatement( "You need atleast " + + hopsData.getSeedAmount() + " seeds to plant here."); + return true; + } + player.startAnimation(FarmingConstants.SEED_DIBBING); + hopsStages[hopsFieldsData.getHopsIndex()] = 4; + player.getItemAssistant().deleteItem(seedId, hopsData.getSeedAmount()); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + hopsState[hopsFieldsData.getHopsIndex()] = 0; + hopsSeeds[hopsFieldsData.getHopsIndex()] = seedId; + hopsTimer[hopsFieldsData.getHopsIndex()] = GameEngine + .getMinutesCounter(); + player.getPlayerAssistant().addSkillXP(hopsData.getPlantingXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateHopsStates(); + player.stopPlayer(false); + } + }, 3); + return true; + } + + /* harvesting the plant resulted */ + + public boolean harvest(int objectX, int objectY) { + final HopsFieldsData hopsFieldsData = HopsFieldsData.forIdPosition( + objectX, objectY); + if (hopsFieldsData == null) { + return false; + } + final HopsData hopsData = HopsData.forId(hopsSeeds[hopsFieldsData + .getHopsIndex()]); + if (hopsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to harvest here."); + return true; + } + player.startAnimation(FarmingConstants.SPADE_ANIM); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (hopsHarvest[hopsFieldsData.getHopsIndex()] == 0) { + hopsHarvest[hopsFieldsData.getHopsIndex()] = 1 + (START_HARVEST_AMOUNT + Misc + .random(END_HARVEST_AMOUNT - START_HARVEST_AMOUNT)) * (1); + } + if (hopsHarvest[hopsFieldsData.getHopsIndex()] == 1) { + resetHops(hopsFieldsData.getHopsIndex()); + hopsStages[hopsFieldsData.getHopsIndex()] = 3; + hopsTimer[hopsFieldsData.getHopsIndex()] = GameEngine + .getMinutesCounter(); + container.stop(); + return; + } + if (player.getItemAssistant().freeSlots() <= 0) { + container.stop(); + return; + } + hopsHarvest[hopsFieldsData.getHopsIndex()]--; + player.startAnimation( + FarmingConstants.SPADE_ANIM); + player.getPacketSender().sendMessage( + "You harvest the crop, and get some vegetables."); + player.getItemAssistant() + .addItem(hopsData.getHarvestId(), 1); + player.getPlayerAssistant().addSkillXP(hopsData.getHarvestXp(), SkillConstants.FARMING.ordinal()); + } + + @Override + public void stop() { + updateHopsStates(); + player.getPlayerAssistant().resetAnimation(); + } + }, 2); + return true; + } + + /* putting compost onto the plant */ + + public boolean putCompost(int objectX, int objectY, final int itemId) { + if (itemId != 6032 && itemId != 6034) { + return false; + } + final HopsFieldsData hopsFieldsData = HopsFieldsData.forIdPosition( + objectX, objectY); + if (hopsFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (hopsStages[hopsFieldsData.getHopsIndex()] != 3 + || hopsState[hopsFieldsData.getHopsIndex()] == 5) { + player.getPacketSender().sendMessage("This patch doesn't need compost."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(1925, 1); + + player.getPacketSender().sendMessage( + "You pour some " + (itemId == 6034 ? "super" : "") + + "compost on the patch."); + player.startAnimation(FarmingConstants.PUTTING_COMPOST); + player.getPlayerAssistant().addSkillXP(itemId == 6034 ? Compost.SUPER_COMPOST_EXP_USE + : Compost.COMPOST_EXP_USE, SkillConstants.FARMING.ordinal()); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[hopsFieldsData.getHopsIndex()] *= itemId == 6032 ? COMPOST_CHANCE + : SUPERCOMPOST_CHANCE; + hopsState[hopsFieldsData.getHopsIndex()] = 5; + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + return true; + } + + /* inspecting a plant */ + + public boolean inspect(int objectX, int objectY) { + final HopsFieldsData hopsFieldsData = HopsFieldsData.forIdPosition( + objectX, objectY); + if (hopsFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + final InspectData inspectData = InspectData + .forId(hopsSeeds[hopsFieldsData.getHopsIndex()]); + final HopsData hopsData = HopsData.forId(hopsSeeds[hopsFieldsData + .getHopsIndex()]); + if (hopsState[hopsFieldsData.getHopsIndex()] == 2) { + player.getDialogueHandler().sendStatement("This plant is diseased. Use a plant cure on it to cure it, ", + "or clear the patch with a spade."); + return true; + } else if (hopsState[hopsFieldsData.getHopsIndex()] == 3) { + player.getDialogueHandler().sendStatement("This plant is dead. You did not cure it while it was diseased.", + "Clear the patch with a spade."); + return true; + } + if (hopsStages[hopsFieldsData.getHopsIndex()] == 0) { + player.getDialogueHandler().sendStatement( + "This is a hops patch. The soil has not been treated.", + "The patch needs weeding."); + } else if (hopsStages[hopsFieldsData.getHopsIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This is a hops patch. The soil has not been treated.", + "The patch is empty and weeded."); + } else if (inspectData != null && hopsData != null) { + player.getPacketSender().sendMessage( + "You bend down and start to inspect the patch..."); + + player.startAnimation(1331); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (hopsStages[hopsFieldsData.getHopsIndex()] - 4 < inspectData + .getMessages().length - 2) { + player.getDialogueHandler().sendStatement( inspectData + .getMessages()[hopsStages[hopsFieldsData + .getHopsIndex()] - 4]); + } else if (hopsStages[hopsFieldsData.getHopsIndex()] < hopsData + .getEndingState() - hopsData.getStartingState() + 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 2]); + } else { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 1]); + } + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(1332); + player.stopPlayer(false); + // player.reset(); + } + }, 5); + } + return true; + } + + /* opening the corresponding guide about the patch */ + + public boolean guide(int objectX, int objectY) { + final HopsFieldsData hopsFieldsData = HopsFieldsData.forIdPosition( + objectX, objectY); + if (hopsFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + player.getSkillInterfaces().farmingComplex(2); + player.getSkillInterfaces().selected = 20; + return true; + } + + /* Curing the plant */ + + public boolean curePlant(int objectX, int objectY, int itemId) { + final HopsFieldsData hopsFieldsData = HopsFieldsData.forIdPosition( + objectX, objectY); + if (hopsFieldsData == null || itemId != 6036) { + return false; + } + final HopsData hopsData = HopsData.forId(hopsSeeds[hopsFieldsData + .getHopsIndex()]); + if (hopsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (hopsState[hopsFieldsData.getHopsIndex()] != 2) { + player.getPacketSender().sendMessage("This plant doesn't need to be cured."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(229, 1); + player.startAnimation(FarmingConstants.CURING_ANIM); + player.stopPlayer(true); + hopsState[hopsFieldsData.getHopsIndex()] = 0; + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender().sendMessage( + "You cure the plant with a plant cure."); + container.stop(); + } + + @Override + public void stop() { + updateHopsStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + + return true; + + } + + private void resetHops(int index) { + hopsSeeds[index] = 0; + hopsState[index] = 0; + diseaseChance[index] = 1; + hopsHarvest[index] = 0; + hasFullyGrown[index] = false; + hopsWatched[index] = false; + } + + /* checking if the patch is raked */ + + public boolean checkIfRaked(int objectX, int objectY) { + final HopsFieldsData hopsFieldsData = HopsFieldsData.forIdPosition( + objectX, objectY); + if (hopsFieldsData == null) + return false; + if (hopsStages[hopsFieldsData.getHopsIndex()] == 3) + return true; + return false; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Patch.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Patch.java deleted file mode 100644 index a023e7cf..00000000 --- a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Patch.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.rebotted.game.content.skills.farming; - -/** - * Patch - * @author Andrew (I'm A Boss on Rune-Server and Mr Extremez on Mopar & Runelocus) - */ - -public enum Patch { - - -} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/PatchState.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/PatchState.java new file mode 100644 index 00000000..69e32a97 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/PatchState.java @@ -0,0 +1,5 @@ +package com.rebotted.game.content.skills.farming; + +public enum PatchState { + EMPTY, DESEASED, DEAD +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Seedling.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Seedling.java new file mode 100644 index 00000000..af9b95cd --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/Seedling.java @@ -0,0 +1,167 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.rebotted.game.content.skills.farming; + +import java.util.HashMap; +import java.util.Map; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemAssistant; +import com.rebotted.game.players.Player; + +/** + * Created by IntelliJ IDEA. User: vayken Date: 18/03/12 Time: 11:00 To change + * this template use File | Settings | File Templates. + */ +public class Seedling { + + private Player player; + + public Seedling(Player player) { + this.player = player; + } + + public enum SeedlingData { + OAK(5312, 5358, 5364, 5370), WILLOW(5313, 5359, 5365, 5371), MAPLE( + 5314, 5360, 5366, 5372), YEW(5315, 5361, 5367, 5373), MAGIC( + 5316, 5362, 5368, 5374), SPIRIT(5317, 5363, 5369, 5375), APPLE( + 5283, 5480, 5488, 5496), BANANA(5284, 5481, 5489, 5497), ORANGE( + 5285, 5482, 5490, 5498), CURRY(5286, 5483, 5491, 5499), PINEAPPLE( + 5287, 5484, 5492, 5500), PAPAYA(5288, 5485, 5493, 5501), PALM( + 5289, 5486, 5494, 5502), CALQUAT(5290, 5487, 5495, 5503); + + private int seedId; + private int unwateredSeedlingId; + private int wateredSeedlingId; + private int saplingId; + + private static Map seeds = new HashMap(); + private static Map unwatered = new HashMap(); + private static Map watered = new HashMap(); + + static { + for (SeedlingData data : SeedlingData.values()) { + seeds.put(data.seedId, data); + unwatered.put(data.unwateredSeedlingId, data); + watered.put(data.wateredSeedlingId, data); + } + } + + SeedlingData(int seedId, int unwateredSeedlingId, + int wateredSeedlingId, int saplingId) { + this.seedId = seedId; + this.unwateredSeedlingId = unwateredSeedlingId; + this.wateredSeedlingId = wateredSeedlingId; + this.saplingId = saplingId; + } + + public static SeedlingData getSeed(int seedId) { + return seeds.get(seedId); + } + + public static SeedlingData getUnwatered(int seedId) { + return unwatered.get(seedId); + } + + public static SeedlingData getWatered(int seedId) { + return watered.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public int getUnwateredSeedlingId() { + return unwateredSeedlingId; + } + + public int getWateredSeedlingId() { + return wateredSeedlingId; + } + + public int getSaplingId() { + return saplingId; + } + } + + public void makeSaplingInInv(int itemId) { + SeedlingData seedlingData = SeedlingData.getWatered(itemId); + if (seedlingData == null) + return; + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(seedlingData.getSaplingId(), 1); + } + + public void makeSaplingInBank(int itemId) { + SeedlingData seedlingData = SeedlingData.getWatered(itemId); + if (seedlingData == null) + return; + player.getItemAssistant().removeItemFromBank(itemId, 1); + player.getItemAssistant().addItemToBank(seedlingData.getSaplingId(), 1); + } + + public boolean waterSeedling(int itemUsed, int usedWith, int itemUsedSlot, + int usedWithSlot) { + SeedlingData seedlingData = SeedlingData.getUnwatered(itemUsed); + if (seedlingData == null) + seedlingData = SeedlingData.getUnwatered(usedWith); + if (seedlingData == null + || (!ItemAssistant.getItemName(itemUsed).toLowerCase() + .contains("watering") && !ItemAssistant.getItemName(usedWith) + .toLowerCase() + .contains("watering"))) + return false; + + if (itemUsed >= 5333 && itemUsed <= 5340) + player.getInventory().set(itemUsedSlot, new Item(itemUsed == 5333 ? itemUsed - 2 : itemUsed - 1)); + if (usedWith >= 5333 && usedWith <= 5340) + player.getInventory().set(usedWithSlot, new Item(usedWith == 5333 ? usedWith - 2 : usedWith - 1)); + + player.getPacketSender().sendMessage( + "You water the " + + ItemAssistant.getItemName(seedlingData.getSeedId()).toLowerCase() + "."); + player.getItemAssistant().deleteItem(seedlingData.getUnwateredSeedlingId(), 1); + player.getItemAssistant().addItem(seedlingData.getWateredSeedlingId(), 1); + return true; + + } + + public boolean placeSeedInPot(int itemUsed, int usedWith, int itemUsedSlot, + int usedWithSlot) { + SeedlingData seedlingData = SeedlingData.getSeed(itemUsed); + if (seedlingData == null) + seedlingData = SeedlingData.getUnwatered(usedWith); + if (seedlingData == null || (itemUsed != 5354 && usedWith != 5354)) + return false; + player.getItemAssistant().deleteItem(seedlingData.getSeedId(), 1); + player.getInventory().set( + itemUsed == 5354 ? itemUsedSlot : usedWithSlot, + new Item(seedlingData.getUnwateredSeedlingId())); + player.getPacketSender().sendMessage( + "You sow some maple tree seeds in the plantpots."); + player.getPacketSender().sendMessage("They need watering before they will grow."); + return true; + } + + public boolean fillPotWithSoil(int itemId, int objectX, int objectY) { + if (itemId != 5350) + return false; + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + + if (!player.getItemAssistant().playerHasItem(FarmingConstants.TROWEL)) { + player.getPacketSender().sendMessage( + "You need a gardening trowel to fill this pot with soil."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.startAnimation(FarmingConstants.FILLING_POT_ANIM); + player.getPacketSender().sendMessage("You fill the empty plant pot with soil."); + player.getItemAssistant().addItem(5354, 1); + return true; + } +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/SpecialPlantOne.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/SpecialPlantOne.java new file mode 100644 index 00000000..46604284 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/SpecialPlantOne.java @@ -0,0 +1,886 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.rebotted.game.content.skills.farming; + +/** + * + * @author ArrowzFtw + */ + +import java.awt.Point; +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.items.ItemAssistant; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; +/** + * Created by IntelliJ IDEA. User: vayken Date: 24/02/12 Time: 20:34 To change + * this template use File | Settings | File Templates. + */ +public class SpecialPlantOne { + + private Player player; + + // set of global constants for Farming + + private static final double COMPOST_CHANCE = 0.9; + private static final double SUPERCOMPOST_CHANCE = 0.7; + private static final double CLEARING_EXPERIENCE = 4; + + public SpecialPlantOne(Player player) { + this.player = player; + } + + // Farming data + public int[] specialPlantStages = new int[4]; + public int[] specialPlantSaplings = new int[4]; + public int[] specialPlantState = new int[4]; + public long[] specialPlantTimer = new long[4]; + public double[] diseaseChance = { 1, 1, 1, 1 }; + public boolean[] hasFullyGrown = { false, false, false, false }; + + public static final int MAIN_SPECIAL_PLANT_CONFIG = 507; + + /* This is the enum holding the saplings info */ + + public enum SpecialPlantData { + SPIRIT_TREE(5375, -1, 1, 83, 3680, 0.15, 199.5, 0, 0x09, 0x14, 0x2c, + 19301.8, 12, 23), CALQUAT_TREE(5503, 5980, 1, 72, 1200, 0.15, + 129.5, 48.5, 0x04, 0x12, 0x22, 12096, 14, 20); + + private int saplingId; + private int harvestId; + private int saplingAmount; + private int levelRequired; + private int growthTime; + private double diseaseChance; + private double plantingXp; + private double harvestXp; + private int startingState; + private int endingState; + private int checkHealthState; + private double checkHealthExperience; + private int diseaseDiffValue; + private int deathDiffValue; + + private static Map saplings = new HashMap(); + + static { + for (SpecialPlantData data : SpecialPlantData.values()) { + saplings.put(data.saplingId, data); + } + } + + SpecialPlantData(int saplingId, int harvestId, int saplingAmount, + int levelRequired, int growthTime, double diseaseChance, + double plantingXp, double harvestXp, int startingState, + int endingState, int checkHealthState, + double checkHealthExperience, int diseaseDiffValue, + int deathDiffValue) { + this.saplingId = saplingId; + this.harvestId = harvestId; + this.saplingAmount = saplingAmount; + this.levelRequired = levelRequired; + this.growthTime = growthTime; + this.diseaseChance = diseaseChance; + this.plantingXp = plantingXp; + this.harvestXp = harvestXp; + this.startingState = startingState; + this.endingState = endingState; + this.checkHealthState = checkHealthState; + this.checkHealthExperience = checkHealthExperience; + this.diseaseDiffValue = diseaseDiffValue; + this.deathDiffValue = deathDiffValue; + } + + public static SpecialPlantData forId(int saplingId) { + return saplings.get(saplingId); + } + + public int getSapplingId() { + return saplingId; + } + + public int getHarvestId() { + return harvestId; + } + + public int getSeedAmount() { + return saplingAmount; + } + + public int getLevelRequired() { + return levelRequired; + } + + public int getGrowthTime() { + return growthTime; + } + + public double getDiseaseChance() { + return diseaseChance; + } + + public double getPlantingXp() { + return plantingXp; + } + + public double getHarvestXp() { + return harvestXp; + } + + public int getStartingState() { + return startingState; + } + + public int getEndingState() { + return endingState; + } + + public int getCheckHealthState() { + return checkHealthState; + } + + public double getCheckHealthXp() { + return checkHealthExperience; + } + + public int getDiseaseDiffValue() { + return diseaseDiffValue; + } + + public int getDeathDiffValue() { + return deathDiffValue; + } + } + + /* This is the enum data about the different patches */ + + public enum SpecialPlantFieldsData { + BRIMHAVEN(0, + new Point[] { new Point(2801, 3202), new Point(2803, 3204) }, + 5375), KARAMJA(1, new Point[] { new Point(2795, 3100), + new Point(2797, 3102) }, 5503), DRAYNOR(2, new Point[] { + new Point(3059, 3257), new Point(3061, 3259) }, 5375), ETCETERIA( + 3, + new Point[] { new Point(2612, 3857), new Point(2614, 3859) }, + 5375); + + private int specialPlantsIndex; + private Point[] specialPlantPosition; + private int seedId; + + SpecialPlantFieldsData(int specialPlantsIndex, + Point[] specialPlantPosition, int seedId) { + this.specialPlantsIndex = specialPlantsIndex; + this.specialPlantPosition = specialPlantPosition; + this.seedId = seedId; + } + + public static SpecialPlantFieldsData forIdPosition(int x, int y) { + for (SpecialPlantFieldsData specialPlantFieldsData : SpecialPlantFieldsData + .values()) { + if (FarmingConstants.inRangeArea( + specialPlantFieldsData.getSpecialPlantPosition()[0], + specialPlantFieldsData.getSpecialPlantPosition()[1], x, + y)) { + return specialPlantFieldsData; + } + } + return null; + } + + public int getSpecialPlantsIndex() { + return specialPlantsIndex; + } + + public Point[] getSpecialPlantPosition() { + return specialPlantPosition; + } + + public int getSaplingd() { + return seedId; + } + } + + /* This is the enum that hold the different data for inspecting the plant */ + + public enum InspectData { + + SPIRIT_TREE( + 5375, + new String[][] { + { "The spirit tree sapling has only just been planted. It has not grown yet." }, + { "The spirit tree has grown slightly, and sprouted a few more leaves." }, + { "Some dark spots have appeared on the trees trunk, and the leaves have grown longer." }, + { "The tree has grown larger in all respects, and has grown more leaves." }, + { + "The spirit tree base has widened showing some roots, and the leaves have morphed into a small canopy.", + "Two small branches have appeared on either side of the trunk." }, + { + "The spirit tree has grown wider in girth, but is still the same height as before.", + "The base is larger as well." }, + { "The spirit tree has grown larger in all respects.", + "The trunk is more warped towards the west, and the roots are more visible" }, + { "The spirit tree is larger in all respects.", + "The trunk has grown in a 'S' shape." }, + { + "The spirit tree has grown another knob on the trunk which will eventually become its nose.", + "The tree is larger in all respects, and its branches are growing out to the sides more." }, + { + "The spirit tree canopy shifts the angle its inclining towards, and its branches are almost parallel to the ground.", + "he nose is more defined, and the tree is slightly larger." }, + { "The spirit tree branches are slightly angling towards the ground, and it is slightly larger than before." }, + { + "The spirit tree canopy is smaller, the face is fully defined and the texture of the tree has changed dramatically", + "The Spirit tree is ready to be checked." } }), CALQUAT_TREE( + 5503, + new String[][] { + { "The calquat sapling has only just been planted." }, + { "The calquat tree grows another segment taller." }, + { "The calquat tree grows another segment taller." }, + { "The calquat tree grows another segment longer and starts a branch midway up its trunk." }, + { "The calquat tree grows some leaves." }, + { "The calquat tree grows another segment upside down and grows leaves on its mid-branch." }, + { "The calquat tree grows towards the ground." }, + { "The calquat tree is ready to be harvested." }, }); + private int saplingId; + private String[][] messages; + + private static Map saplings = new HashMap(); + + static { + for (InspectData data : InspectData.values()) { + saplings.put(data.saplingId, data); + } + } + + InspectData(int saplingId, String[][] messages) { + this.saplingId = saplingId; + this.messages = messages; + } + + public static InspectData forId(int saplingId) { + return saplings.get(saplingId); + } + + public int getSeedId() { + return saplingId; + } + + public String[][] getMessages() { + return messages; + } + } + + /* update all the patch states */ + + public void updateSpecialPlants() { + // brimhaven - karamja - draynor - Etceteria + int[] configValues = new int[specialPlantStages.length]; + + int configValue; + for (int i = 0; i < specialPlantStages.length; i++) { + configValues[i] = getConfigValue(specialPlantStages[i], + specialPlantSaplings[i], specialPlantState[i], i); + } + + configValue = (configValues[0] << 16) + (configValues[1] << 8 << 16) + + configValues[2] + (configValues[3] << 8); + player.getPacketSender().sendConfig(MAIN_SPECIAL_PLANT_CONFIG, configValue); + } + + /* getting the different config values */ + + public int getConfigValue(int specialStage, int saplingId, int plantState, + int index) { + SpecialPlantData specialPlantData = SpecialPlantData.forId(saplingId); + switch (specialStage) { + case 0:// weed + return 0x00; + case 1:// weed cleared + return 0x01; + case 2: + return 0x02; + case 3: + return 0x03; + } + if (specialPlantData == null) { + return -1; + } + if (specialStage > specialPlantData.getEndingState() + - specialPlantData.getStartingState() - 1) { + hasFullyGrown[index] = true; + } + if (getPlantState(plantState, specialPlantData, specialStage) == 3) + return specialPlantData.getCheckHealthState(); + + return getPlantState(plantState, specialPlantData, specialStage); + } + + /* getting the plant states */ + + public int getPlantState(int plantState, SpecialPlantData specialPlantData, + int specialStage) { + int value = specialPlantData.getStartingState() + specialStage - 4; + switch (plantState) { + case 0: + return value; + case 1: + return value + specialPlantData.getDiseaseDiffValue(); + case 2: + return value + specialPlantData.getDeathDiffValue(); + case 3: + return specialPlantData.getCheckHealthState(); + } + return -1; + } + + /* calculating the disease chance and making the plant grow */ + + public void doCalculations() { + for (int i = 0; i < specialPlantSaplings.length; i++) { + if (specialPlantStages[i] > 0 + && specialPlantStages[i] <= 3 + && GameEngine.getMinutesCounter() - specialPlantTimer[i] >= 5) { + specialPlantStages[i]--; + specialPlantTimer[i] = GameEngine.getMinutesCounter(); + updateSpecialPlants(); + continue; + } + SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSaplings[i]); + if (specialPlantData == null) { + continue; + } + + long difference = GameEngine.getMinutesCounter() + - specialPlantTimer[i]; + long growth = specialPlantData.getGrowthTime(); + int nbStates = specialPlantData.getEndingState() + - specialPlantData.getStartingState(); + int state = (int) (difference * nbStates / growth); + if (specialPlantTimer[i] == 0 || specialPlantState[i] == 2 + || specialPlantState[i] == 3 || (state > nbStates)) { + continue; + } + if (4 + state != specialPlantStages[i] + && specialPlantStages[i] <= specialPlantData + .getEndingState() + - specialPlantData.getStartingState() + + (specialPlantData == SpecialPlantData.SPIRIT_TREE ? 3 + : -2)) { + if (specialPlantStages[i] == specialPlantData.getEndingState() + - specialPlantData.getStartingState() + + (specialPlantData == SpecialPlantData.SPIRIT_TREE ? 3 + : -2)) { + specialPlantStages[i] = specialPlantData.getEndingState() + - specialPlantData.getStartingState() + 7; + specialPlantState[i] = 3; + updateSpecialPlants(); + return; + } + specialPlantStages[i] = 4 + state; + doStateCalculation(i); + updateSpecialPlants(); + } + } + } + + public void modifyStage(int i) { + SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSaplings[i]); + if (specialPlantData == null) + return; + long difference = GameEngine.getMinutesCounter() - specialPlantTimer[i]; + long growth = specialPlantData.getGrowthTime(); + int nbStates = specialPlantData.getEndingState() + - specialPlantData.getStartingState(); + int state = (int) (difference * nbStates / growth); + specialPlantStages[i] = 4 + state; + updateSpecialPlants(); + + } + + /* calculations about the diseasing chance */ + + public void doStateCalculation(int index) { + if (specialPlantState[index] == 2) { + return; + } + // if the patch is diseased, it dies, if its watched by a farmer, it + // goes back to normal + if (specialPlantState[index] == 1) { + specialPlantState[index] = 2; + } + + if (specialPlantState[index] == 5 && specialPlantStages[index] != 2) { + specialPlantState[index] = 0; + } + + if (specialPlantState[index] == 0 && specialPlantStages[index] >= 5 + && !hasFullyGrown[index]) { + SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSaplings[index]); + if (specialPlantData == null) { + return; + } + + double chance = diseaseChance[index] + * specialPlantData.getDiseaseChance(); + int maxChance = (int) chance * 100; + if (Misc.random(100) < maxChance) { + specialPlantState[index] = 1; + } + } + } + + /* clearing the patch with a rake of a spade */ + + public boolean clearPatch(int objectX, int objectY, int itemId) { + final SpecialPlantFieldsData hopsFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + int finalAnimation; + int finalDelay; + if (hopsFieldsData == null + || (itemId != FarmingConstants.RAKE && itemId != FarmingConstants.SPADE)) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] == 3) { + return true; + } + if (specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] <= 3) { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a rake to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.RAKING_ANIM; + finalDelay = 5; + } + } else { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.SPADE_ANIM; + finalDelay = 3; + } + } + final int animation = finalAnimation; + player.stopPlayer(true); + player.startAnimation(animation); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.startAnimation(animation); + if (specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] <= 2) { + specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()]++; + player.getItemAssistant().addItem(6055, 1); + } else { + specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] = 3; + container.stop(); + } + player.getPlayerAssistant().addSkillXP(CLEARING_EXPERIENCE, SkillConstants.FARMING.ordinal()); + specialPlantTimer[hopsFieldsData.getSpecialPlantsIndex()] = GameEngine + .getMinutesCounter(); + updateSpecialPlants(); + if (specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] == 3) { + container.stop(); + return; + } + } + + @Override + public void stop() { + resetSpecialPlants(hopsFieldsData.getSpecialPlantsIndex()); + player.getPacketSender().sendMessage("You clear the patch."); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, finalDelay); + return true; + + } + + /* planting the saplings */ + + public boolean plantSapling(int objectX, int objectY, final int saplingId) { + final SpecialPlantFieldsData specialPlantFieldData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + final SpecialPlantData specialPlantData = SpecialPlantData + .forId(saplingId); + if (specialPlantFieldData == null || specialPlantData == null + || specialPlantFieldData.getSaplingd() != saplingId) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if ((specialPlantStages[0] > 3 || specialPlantStages[2] > 3 || specialPlantStages[3] > 3) + && (specialPlantFieldData.getSpecialPlantsIndex() != 1)) { + player.getPacketSender().sendMessage( + "You already have a spirit tree planted somewhere else."); + return true; + + } + if (specialPlantStages[specialPlantFieldData.getSpecialPlantsIndex()] != 3) { + player.getPacketSender().sendMessage("You can't plant a sapling here."); + return true; + } + if (specialPlantData.getLevelRequired() > player.playerLevel[SkillConstants.FARMING.ordinal()]) { + player.getDialogueHandler().sendStatement("You need a farming level of " + + specialPlantData.getLevelRequired() + + " to plant this sapling."); + return true; + } + + if (!player.getItemAssistant().playerHasItem(FarmingConstants.TROWEL)) { + player.getDialogueHandler().sendStatement( + "You need a trowel to plant the sapling here."); + return true; + } + player.startAnimation( + FarmingConstants.PLANTING_POT_ANIM); + specialPlantStages[specialPlantFieldData.getSpecialPlantsIndex()] = 4; + player.getItemAssistant().deleteItem(saplingId, 1); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + specialPlantState[specialPlantFieldData.getSpecialPlantsIndex()] = 0; + specialPlantSaplings[specialPlantFieldData + .getSpecialPlantsIndex()] = saplingId; + specialPlantTimer[specialPlantFieldData.getSpecialPlantsIndex()] = GameEngine + .getMinutesCounter(); + player.getPlayerAssistant().addSkillXP(specialPlantData.getPlantingXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateSpecialPlants(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 3); + return true; + } + + /* harvesting the plant resulted */ + + public boolean harvestOrCheckHealth(int objectX, int objectY) { + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null) { + return false; + } + final SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSaplings[specialPlantFieldsData + .getSpecialPlantsIndex()]); + if (specialPlantData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (specialPlantData == SpecialPlantData.SPIRIT_TREE + && specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] != 3) { + handleSpiritTree(); + return true; + } + if (player.getItemAssistant().freeSlots() <= 0) { + player.getPacketSender().sendMessage("Not enough space in your inventory."); + return true; + } + player.startAnimation(832); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (player.getItemAssistant().freeSlots() <= 0) { + container.stop(); + return; + } + + if (specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] == 3) { + player.getPacketSender() + .sendMessage( + "You examine the plant for signs of disease and find that it's in perfect health."); + player.getPlayerAssistant().addSkillXP(specialPlantData.getCheckHealthXp(), SkillConstants.FARMING.ordinal()); + specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] = 0; + hasFullyGrown[specialPlantFieldsData + .getSpecialPlantsIndex()] = false; + specialPlantTimer[specialPlantFieldsData + .getSpecialPlantsIndex()] = GameEngine + .getMinutesCounter() + - specialPlantData.getGrowthTime(); + modifyStage(specialPlantFieldsData.getSpecialPlantsIndex()); + container.stop(); + return; + } + player.getPacketSender().sendMessage( + "You harvest the crop, and pick some " + + ItemAssistant.getItemName(specialPlantData.getHarvestId()).toLowerCase() + "."); + player.getItemAssistant().addItem( + specialPlantData.getHarvestId(), 1); + player.getPlayerAssistant().addSkillXP(specialPlantData.getHarvestXp(), SkillConstants.FARMING.ordinal()); + specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()]--; + updateSpecialPlants(); + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 2); + return true; + } + + private void handleSpiritTree() { + // SpiritTree.sendDialogue(player, 3636); + } + + /* lowering the stage */ + + public void lowerStage(int index, int timer) { + hasFullyGrown[index] = false; + specialPlantTimer[index] -= timer; + } + + /* putting compost onto the plant */ + + public boolean putCompost(int objectX, int objectY, final int itemId) { + if (itemId != 6032 && itemId != 6034) { + return false; + } + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (specialPlantStages[specialPlantFieldsData.getSpecialPlantsIndex()] != 3 + || specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] == 5) { + player.getPacketSender().sendMessage("This patch doesn't need compost."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(1925, 1); + + player.getPacketSender().sendMessage( + "You pour some " + (itemId == 6034 ? "super" : "") + + "compost on the patch."); + player.startAnimation(FarmingConstants.PUTTING_COMPOST); + player.getPlayerAssistant().addSkillXP(itemId == 6034 ? Compost.SUPER_COMPOST_EXP_USE + : Compost.COMPOST_EXP_USE, SkillConstants.FARMING.ordinal()); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[specialPlantFieldsData.getSpecialPlantsIndex()] *= itemId == 6032 ? COMPOST_CHANCE + : SUPERCOMPOST_CHANCE; + specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] = 5; + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + return true; + } + + /* inspecting a plant */ + + public boolean inspect(int objectX, int objectY) { + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + final InspectData inspectData = InspectData + .forId(specialPlantSaplings[specialPlantFieldsData + .getSpecialPlantsIndex()]); + final SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSaplings[specialPlantFieldsData + .getSpecialPlantsIndex()]); + if (specialPlantState[specialPlantFieldsData.getSpecialPlantsIndex()] == 1) { + player.getDialogueHandler().sendStatement("This plant is diseased. Use a plant cure on it to cure it, ", + "or clear the patch with a spade."); + return true; + } else if (specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] == 2) { + player.getDialogueHandler().sendStatement("This plant is dead. You did not cure it while it was diseased.", + "Clear the patch with a spade."); + return true; + } else if (specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This plant has fully grown. You can check it's health", + "to gain some farming experiences."); + return true; + } + if (specialPlantStages[specialPlantFieldsData.getSpecialPlantsIndex()] == 0) { + player.getDialogueHandler().sendStatement("This is one of the special patches. The soil has not been treated.", + "The patch needs weeding."); + } else if (specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] == 3) { + player.getDialogueHandler().sendStatement("This is one of the special patches. The soil has not been treated.", + "The patch is empty and weeded."); + } else if (inspectData != null && specialPlantData != null) { + player.getPacketSender().sendMessage( + "You bend down and start to inspect the patch..."); + + player.startAnimation(1331); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] - 4 < inspectData + .getMessages().length - 2) { + player.getDialogueHandler().sendStatement(inspectData.getMessages()[specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] - 4]); + } else if (specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] < specialPlantData + .getEndingState() + - specialPlantData.getStartingState() + 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 2]); + } else { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 1]); + } + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(1332); + player.stopPlayer(false); + } + }, 5); + } + return true; + } + + /* opening the corresponding guide about the patch */ + + public boolean guide(int objectX, int objectY) { + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + player.getSkillInterfaces().farmingComplex(8); + player.getSkillInterfaces().selected = 20; + return true; + } + + /* Curing the plant */ + + public boolean curePlant(int objectX, int objectY, int itemId) { + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null || itemId != 6036) { + return false; + } + final SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSaplings[specialPlantFieldsData + .getSpecialPlantsIndex()]); + if (specialPlantData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (specialPlantState[specialPlantFieldsData.getSpecialPlantsIndex()] != 1) { + player.getPacketSender().sendMessage("This plant doesn't need to be cured."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(229, 1); + player.startAnimation(FarmingConstants.CURING_ANIM); + player.stopPlayer(true); + specialPlantState[specialPlantFieldsData.getSpecialPlantsIndex()] = 0; + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender().sendMessage( + "You cure the plant with a plant cure."); + container.stop(); + } + + @Override + public void stop() { + updateSpecialPlants(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + + return true; + + } + + private void resetSpecialPlants(int index) { + specialPlantSaplings[index] = 0; + specialPlantState[index] = 0; + diseaseChance[index] = 1; + hasFullyGrown[index] = false; + } + + /* checking if the patch is raked */ + + public boolean checkIfRaked(int objectX, int objectY) { + final SpecialPlantFieldsData specialPlantFieldData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldData == null) + return false; + if (specialPlantStages[specialPlantFieldData.getSpecialPlantsIndex()] == 3) + return true; + return false; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/SpecialPlantTwo.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/SpecialPlantTwo.java new file mode 100644 index 00000000..48ce2667 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/SpecialPlantTwo.java @@ -0,0 +1,892 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.rebotted.game.content.skills.farming; + +/** + * + * @author ArrowzFtw + */ + +import java.awt.Point; +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; + +/** + * Created by IntelliJ IDEA. User: vayken Date: 24/02/12 Time: 20:34 To change + * this template use File | Settings | File Templates. + */ +public class SpecialPlantTwo { + + private Player player; + + // set of global constants for Farming + + private static final double COMPOST_CHANCE = 0.9; + private static final double SUPERCOMPOST_CHANCE = 0.7; + private static final double CLEARING_EXPERIENCE = 4; + + public SpecialPlantTwo(Player player) { + this.player = player; + } + + // Farming data + public int[] specialPlantStages = new int[4]; + public int[] specialPlantSeeds = new int[4]; + public int[] specialPlantState = new int[4]; + public long[] specialPlantTimer = new long[4]; + public double[] diseaseChance = { 1, 1, 1, 1 }; + public boolean[] hasFullyGrown = { false, false, false, false }; + + public static final int MAIN_SPECIAL_PLANT_CONFIG = 512; + + /* This is the enum holding the seeds info */ + + public enum SpecialPlantData { + BELLADONNA(5281, 2398, 1, 63, 280, 0.15, 91, 512, 0x04, 0x08, -1, 0, 5, + 8), CACTUS(5280, 6016, 1, 55, 550, 0.15, 66.5, 25, 0x08, 0x12, + 0x1f, 374, 11, 17), BITTERCAP(5282, 6004, 1, 53, 220, 0.15, + 61.5, 57.7, 0x04, 0x0f, -1, 0, 12, 17); + + private int seedId; + private int harvestId; + private int seedAmount; + private int levelRequired; + private int growthTime; + private double diseaseChance; + private double plantingXp; + private double harvestXp; + private int startingState; + private int endingState; + private int checkHealthState; + private double checkHealthExperience; + private int diseaseDiffValue; + private int deathDiffValue; + + private static Map seeds = new HashMap(); + + static { + for (SpecialPlantData data : SpecialPlantData.values()) { + seeds.put(data.seedId, data); + } + } + + SpecialPlantData(int seedId, int harvestId, int seedAmount, + int levelRequired, int growthTime, double diseaseChance, + double plantingXp, double harvestXp, int startingState, + int endingState, int checkHealthState, + double checkHealthExperience, int diseaseDiffValue, + int deathDiffValue) { + this.seedId = seedId; + this.harvestId = harvestId; + this.seedAmount = seedAmount; + this.levelRequired = levelRequired; + this.growthTime = growthTime; + this.diseaseChance = diseaseChance; + this.plantingXp = plantingXp; + this.harvestXp = harvestXp; + this.startingState = startingState; + this.endingState = endingState; + this.checkHealthState = checkHealthState; + this.checkHealthExperience = checkHealthExperience; + this.diseaseDiffValue = diseaseDiffValue; + this.deathDiffValue = deathDiffValue; + } + + public static SpecialPlantData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public int getHarvestId() { + return harvestId; + } + + public int getSeedAmount() { + return seedAmount; + } + + public int getLevelRequired() { + return levelRequired; + } + + public int getGrowthTime() { + return growthTime; + } + + public double getDiseaseChance() { + return diseaseChance; + } + + public double getPlantingXp() { + return plantingXp; + } + + public double getHarvestXp() { + return harvestXp; + } + + public int getStartingState() { + return startingState; + } + + public int getEndingState() { + return endingState; + } + + public int getCheckHealthState() { + return checkHealthState; + } + + public double getCheckHealthXp() { + return checkHealthExperience; + } + + public int getDiseaseDiffValue() { + return diseaseDiffValue; + } + + public int getDeathDiffValue() { + return deathDiffValue; + } + } + + /* This is the enum data about the different patches */ + + public enum SpecialPlantFieldsData { + DRAYNOR_MANOR(0, new Point[] { new Point(3086, 3354), + new Point(3087, 3355) }, 5281), AL_KARID(2, new Point[] { + new Point(3315, 3202), new Point(3316, 3203) }, 5280), CANIFIS( + 3, + new Point[] { new Point(3451, 3472), new Point(3452, 3473) }, + 5282); + + private int specialPlantsIndex; + private Point[] specialPlantPosition; + private int seedId; + + SpecialPlantFieldsData(int specialPlantsIndex, + Point[] specialPlantPosition, int seedId) { + this.specialPlantsIndex = specialPlantsIndex; + this.specialPlantPosition = specialPlantPosition; + this.seedId = seedId; + } + + public static SpecialPlantFieldsData forIdPosition(int x, int y) { + for (SpecialPlantFieldsData specialPlantFieldsData : SpecialPlantFieldsData + .values()) { + if (FarmingConstants.inRangeArea( + specialPlantFieldsData.getSpecialPlantPosition()[0], + specialPlantFieldsData.getSpecialPlantPosition()[1], x, + y)) { + return specialPlantFieldsData; + } + } + return null; + } + + public int getSpecialPlantsIndex() { + return specialPlantsIndex; + } + + public Point[] getSpecialPlantPosition() { + return specialPlantPosition; + } + + public int getSeedId() { + return seedId; + } + } + + /* This is the enum that hold the different data for inspecting the plant */ + + public enum InspectData { + BELLADONNA(5281, new String[][] { + { "The belladonna seed has only just been planted." }, + { "The belladonna plant grows a little taller." }, + { "The belladonna plant grows taller and leafier." }, + { "The belladonna plant grows some flower buds." }, + { "The belladonna plant is ready to harvest." } }), CACTUS( + 5280, + new String[][] { + { "The cactus seed has only just been planted." }, + { "The cactus grows taller." }, + { "The cactus grows two small stumps." }, + { "The cactus grows its stumps longer." }, + { "The cactus grows larger." }, + { "The cactus curves its arms upwards and grows another stump." }, + { "The cactus grows all three of its arms upwards." }, + { "The cactus is ready to be harvested." } }), BITTERCAP( + 5282, new String[][] { + { "The mushroom spore has only just been planted." }, + { "The mushrooms grow a little taller." }, + { "The mushrooms grow a little taller." }, + { "The mushrooms grow a little larger." }, + { "The mushrooms grow a little larger." }, + { "The mushrooms tops grow a little wider." }, + { "The mushrooms are ready to harvest." } }); + + private int seedId; + private String[][] messages; + + private static Map seeds = new HashMap(); + + static { + for (InspectData data : InspectData.values()) { + seeds.put(data.seedId, data); + } + } + + InspectData(int seedId, String[][] messages) { + this.seedId = seedId; + this.messages = messages; + } + + public static InspectData forId(int seedId) { + return seeds.get(seedId); + } + + public int getSeedId() { + return seedId; + } + + public String[][] getMessages() { + return messages; + } + } + + /* update all the patch states */ + + public void updateSpecialPlants() { + // draynor manor - none - al karid - canifis + int[] configValues = new int[specialPlantStages.length]; + + int configValue; + for (int i = 0; i < specialPlantStages.length; i++) { + configValues[i] = getConfigValue(specialPlantStages[i], + specialPlantSeeds[i], specialPlantState[i], i); + } + + configValue = (configValues[0] << 16) + (configValues[1] << 8 << 16) + + configValues[2] + (configValues[3] << 8); + player.getPacketSender().sendConfig(MAIN_SPECIAL_PLANT_CONFIG, configValue); + } + + /* getting the different config values */ + + public int getConfigValue(int specialStage, int seedId, int plantState, + int index) { + SpecialPlantData specialPlantData = SpecialPlantData.forId(seedId); + switch (specialStage) { + case 0:// weed + return 0x00; + case 1:// weed cleared + return 0x01; + case 2: + return 0x02; + case 3: + return 0x03; + } + if (specialPlantData == null) { + return -1; + } + if (specialStage > specialPlantData.getEndingState() + - specialPlantData.getStartingState() - 1) { + hasFullyGrown[index] = true; + } + if (getPlantState(plantState, specialPlantData, specialStage) == 3) + return specialPlantData.getCheckHealthState(); + + return getPlantState(plantState, specialPlantData, specialStage); + } + + /* getting the plant states */ + + public int getPlantState(int plantState, SpecialPlantData specialPlantData, + int specialStage) { + int value = specialPlantData.getStartingState() + specialStage - 4; + switch (plantState) { + case 0: + return value; + case 1: + return value + specialPlantData.getDiseaseDiffValue(); + case 2: + return value + specialPlantData.getDeathDiffValue(); + case 3: + return specialPlantData.getCheckHealthState(); + } + return -1; + } + + /* calculating the disease chance and making the plant grow */ + + public void doCalculations() { + for (int i = 0; i < specialPlantSeeds.length; i++) { + if (specialPlantStages[i] > 0 + && specialPlantStages[i] <= 3 + && GameEngine.getMinutesCounter() - specialPlantTimer[i] >= 5) { + specialPlantStages[i]--; + specialPlantTimer[i] = GameEngine.getMinutesCounter(); + updateSpecialPlants(); + continue; + } + SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSeeds[i]); + if (specialPlantData == null) { + continue; + } + + long difference = GameEngine.getMinutesCounter() + - specialPlantTimer[i]; + long growth = specialPlantData.getGrowthTime(); + int nbStates = specialPlantData.getEndingState() + - specialPlantData.getStartingState(); + int state = (int) (difference * nbStates / growth); + if (specialPlantTimer[i] == 0 || specialPlantState[i] == 2 + || specialPlantState[i] == 3 || (state > nbStates)) { + continue; + } + if (4 + state != specialPlantStages[i] + && specialPlantStages[i] <= specialPlantData + .getEndingState() + - specialPlantData.getStartingState() + + (specialPlantData == SpecialPlantData.BELLADONNA ? 5 + : -2)) { + if (specialPlantStages[i] == specialPlantData.getEndingState() + - specialPlantData.getStartingState() - 2 + && specialPlantData.getCheckHealthState() != -1) { + specialPlantStages[i] = specialPlantData.getEndingState() + - specialPlantData.getStartingState() + 4; + specialPlantState[i] = 3; + updateSpecialPlants(); + return; + } + specialPlantStages[i] = 4 + state; + doStateCalculation(i); + updateSpecialPlants(); + } + } + } + + public void modifyStage(int i) { + SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSeeds[i]); + if (specialPlantData == null) + return; + long difference = GameEngine.getMinutesCounter() - specialPlantTimer[i]; + long growth = specialPlantData.getGrowthTime(); + int nbStates = specialPlantData.getEndingState() + - specialPlantData.getStartingState(); + int state = (int) (difference * nbStates / growth); + specialPlantStages[i] = 4 + state; + updateSpecialPlants(); + + } + + /* calculations about the diseasing chance */ + + public void doStateCalculation(int index) { + if (specialPlantState[index] == 2) { + return; + } + // if the patch is diseased, it dies, if its watched by a farmer, it + // goes back to normal + if (specialPlantState[index] == 1) { + specialPlantState[index] = 2; + } + + if (specialPlantState[index] == 5 && specialPlantStages[index] != 2) { + specialPlantState[index] = 0; + } + + if (specialPlantState[index] == 0 && specialPlantStages[index] >= 5 + && !hasFullyGrown[index]) { + SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSeeds[index]); + if (specialPlantData == null) { + return; + } + + double chance = diseaseChance[index] + * specialPlantData.getDiseaseChance(); + int maxChance = (int) chance * 100; + if (Misc.random(100) <= maxChance) { + specialPlantState[index] = 1; + } + } + } + + /* clearing the patch with a rake of a spade */ + + public boolean clearPatch(int objectX, int objectY, int itemId) { + final SpecialPlantFieldsData hopsFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + int finalAnimation; + int finalDelay; + if (hopsFieldsData == null + || (itemId != FarmingConstants.RAKE && itemId != FarmingConstants.SPADE)) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] == 3) { + return true; + } + if (specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] <= 3) { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a rake to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.RAKING_ANIM; + finalDelay = 5; + } + } else { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.SPADE_ANIM; + finalDelay = 3; + } + } + final int animation = finalAnimation; + player.stopPlayer(true); + player.startAnimation(animation); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.startAnimation(animation); + if (specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] <= 2) { + specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()]++; + player.getItemAssistant().addItem(6055, 1); + } else { + specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] = 3; + container.stop(); + } + player.getPlayerAssistant().addSkillXP(CLEARING_EXPERIENCE, SkillConstants.FARMING.ordinal()); + specialPlantTimer[hopsFieldsData.getSpecialPlantsIndex()] = GameEngine + .getMinutesCounter(); + updateSpecialPlants(); + if (specialPlantStages[hopsFieldsData.getSpecialPlantsIndex()] == 3) { + container.stop(); + return; + } + } + + @Override + public void stop() { + resetSpecialPlants(hopsFieldsData.getSpecialPlantsIndex()); + player.getPacketSender().sendMessage("You clear the patch."); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, finalDelay); + return true; + + } + + /* planting the seeds */ + + public boolean plantSeeds(int objectX, int objectY, final int seedId) { + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + final SpecialPlantData specialPlantData = SpecialPlantData + .forId(seedId); + if (specialPlantFieldsData == null || specialPlantData == null + || specialPlantFieldsData.getSeedId() != seedId) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (specialPlantStages[specialPlantFieldsData.getSpecialPlantsIndex()] != 3) { + player.getPacketSender().sendMessage("You can't plant a seed here."); + return false; + } + if (specialPlantData.getLevelRequired() > player.playerLevel[SkillConstants.FARMING.ordinal()]) { + player.getDialogueHandler().sendStatement("You need a farming level of " + + specialPlantData.getLevelRequired() + + " to plant this seed."); + return true; + } + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SEED_DIBBER)) { + player.getDialogueHandler().sendStatement( + "You need a seed dibber to plant seed here."); + return true; + } + if (player.getItemAssistant().getItemAmount(specialPlantData.getSeedId()) < specialPlantData + .getSeedAmount()) { + player.getDialogueHandler().sendStatement( "You need atleast " + + specialPlantData.getSeedAmount() + + " seeds to plant here."); + return true; + } + player.startAnimation(FarmingConstants.SEED_DIBBING); + specialPlantStages[specialPlantFieldsData.getSpecialPlantsIndex()] = 4; + player.getItemAssistant().deleteItem(seedId, specialPlantData.getSeedAmount()); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] = 0; + specialPlantSeeds[specialPlantFieldsData + .getSpecialPlantsIndex()] = seedId; + specialPlantTimer[specialPlantFieldsData + .getSpecialPlantsIndex()] = GameEngine + .getMinutesCounter(); + player.getPlayerAssistant().addSkillXP(specialPlantData.getPlantingXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateSpecialPlants(); + player.stopPlayer(false); + } + }, 3); + return true; + } + + /* harvesting the plant resulted */ + + public boolean harvestOrCheckHealth(int objectX, int objectY) { + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null) { + return false; + } + final SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSeeds[specialPlantFieldsData + .getSpecialPlantsIndex()]); + if (specialPlantData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (player.getItemAssistant().freeSlots() <= 0) { + player.getPacketSender().sendMessage("Not enough space in your inventory."); + return true; + } + player.stopPlayer(true); + player.startAnimation(832); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (player.getItemAssistant().freeSlots() <= 0) { + container.stop(); + return; + } + + if (specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] == 3) { + player.getPacketSender() + .sendMessage( + "You examine the plant for signs of disease and find that it's in perfect health."); + player.getPlayerAssistant().addSkillXP(specialPlantData.getCheckHealthXp(), SkillConstants.FARMING.ordinal()); + specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] = 0; + hasFullyGrown[specialPlantFieldsData + .getSpecialPlantsIndex()] = false; + specialPlantTimer[specialPlantFieldsData + .getSpecialPlantsIndex()] = GameEngine + .getMinutesCounter() + - specialPlantData.getGrowthTime(); + modifyStage(specialPlantFieldsData.getSpecialPlantsIndex()); + container.stop(); + return; + } + player.getPacketSender().sendMessage( + "You harvest the crop, and pick some " + + specialPlantData.getHarvestId() + "."); + player.getItemAssistant().addItem(specialPlantData.getHarvestId(), 1); + player.getPlayerAssistant().addSkillXP(specialPlantData.getHarvestXp(), SkillConstants.FARMING.ordinal()); + + switch (specialPlantData) { + case BELLADONNA: + resetSpecialPlants(specialPlantFieldsData + .getSpecialPlantsIndex()); + specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] = 3; + specialPlantTimer[specialPlantFieldsData + .getSpecialPlantsIndex()] = GameEngine + .getMinutesCounter(); + break; + case CACTUS: + specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()]--; + break; + case BITTERCAP: + specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()]++; + if (specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] == 16) { + resetSpecialPlants(specialPlantFieldsData + .getSpecialPlantsIndex()); + specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] = 3; + specialPlantTimer[specialPlantFieldsData + .getSpecialPlantsIndex()] = GameEngine + .getMinutesCounter(); + } + break; + } + updateSpecialPlants(); + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 2); + return true; + } + + /* lowering the stage */ + + public void lowerStage(int index, int timer) { + hasFullyGrown[index] = false; + specialPlantTimer[index] -= timer; + } + + /* putting compost onto the plant */ + + public boolean putCompost(int objectX, int objectY, final int itemId) { + if (itemId != 6032 && itemId != 6034) { + return false; + } + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (specialPlantStages[specialPlantFieldsData.getSpecialPlantsIndex()] != 3 + || specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] == 5) { + player.getPacketSender().sendMessage("This patch doesn't need compost."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(1925, 1); + + player.getPacketSender().sendMessage( + "You pour some " + (itemId == 6034 ? "super" : "") + + "compost on the patch."); + player.startAnimation(FarmingConstants.PUTTING_COMPOST); + player.getPlayerAssistant().addSkillXP(itemId == 6034 ? Compost.SUPER_COMPOST_EXP_USE + : Compost.COMPOST_EXP_USE, SkillConstants.FARMING.ordinal()); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + diseaseChance[specialPlantFieldsData.getSpecialPlantsIndex()] *= itemId == 6032 ? COMPOST_CHANCE + : SUPERCOMPOST_CHANCE; + specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] = 5; + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + return true; + } + + /* inspecting a plant */ + + public boolean inspect(int objectX, int objectY) { + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + final InspectData inspectData = InspectData + .forId(specialPlantSeeds[specialPlantFieldsData + .getSpecialPlantsIndex()]); + final SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSeeds[specialPlantFieldsData + .getSpecialPlantsIndex()]); + if (specialPlantState[specialPlantFieldsData.getSpecialPlantsIndex()] == 1) { + player.getDialogueHandler().sendStatement("This plant is diseased. Use a plant cure on it to cure it, ", + "or clear the patch with a spade."); + return true; + } else if (specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] == 2) { + player.getDialogueHandler().sendStatement("This plant is dead. You did not cure it while it was diseased.", + "Clear the patch with a spade."); + return true; + } else if (specialPlantState[specialPlantFieldsData + .getSpecialPlantsIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This plant has fully grown. You can check it's health", + "to gain some farming experiences."); + return true; + } + if (specialPlantStages[specialPlantFieldsData.getSpecialPlantsIndex()] == 0) { + player.getDialogueHandler().sendStatement( + "This is one of the special patches. The soil has not been treated.", + "The patch needs weeding."); + } else if (specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This is one of the special patches. The soil has not been treated.", + "The patch is empty and weeded."); + } else if (inspectData != null && specialPlantData != null) { + player.getPacketSender().sendMessage( + "You bend down and start to inspect the patch..."); + + player.startAnimation(1331); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] - 4 < inspectData + .getMessages().length - 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] - 4]); + } else if (specialPlantStages[specialPlantFieldsData + .getSpecialPlantsIndex()] < specialPlantData + .getEndingState() + - specialPlantData.getStartingState() + 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 2]); + } else { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 1]); + } + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(1332); + player.stopPlayer(false); + // player.reset(); + } + }, 5); + } + return true; + } + + /* opening the corresponding guide about the patch */ + + public boolean guide(int objectX, int objectY) { + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + player.getSkillInterfaces().farmingComplex(8); + player.getSkillInterfaces().selected = 20; + return true; + } + + /* Curing the plant */ + + public boolean curePlant(int objectX, int objectY, int itemId) { + final SpecialPlantFieldsData specialPlantFieldsData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldsData == null || itemId != 6036) { + return false; + } + final SpecialPlantData specialPlantData = SpecialPlantData + .forId(specialPlantSeeds[specialPlantFieldsData + .getSpecialPlantsIndex()]); + if (specialPlantData == null) { + return false; + } + if (!SkillConstants.getEnabled(SkillConstants.FARMING.ordinal())) { + player.getPacketSender().sendMessage("This skill is currently disabled."); + return true; + } + if (specialPlantState[specialPlantFieldsData.getSpecialPlantsIndex()] != 1) { + player.getPacketSender().sendMessage("This plant doesn't need to be cured."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(229, 1); + player.startAnimation(FarmingConstants.CURING_ANIM); + player.stopPlayer(true); + specialPlantState[specialPlantFieldsData.getSpecialPlantsIndex()] = 0; + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender().sendMessage( + "You cure the plant with a plant cure."); + container.stop(); + } + + @Override + public void stop() { + updateSpecialPlants(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + + return true; + + } + + private void resetSpecialPlants(int index) { + specialPlantSeeds[index] = 0; + specialPlantState[index] = 0; + diseaseChance[index] = 1; + hasFullyGrown[index] = false; + } + + /* checking if the patch is raked */ + + public boolean checkIfRaked(int objectX, int objectY) { + final SpecialPlantFieldsData specialPlantFieldData = SpecialPlantFieldsData + .forIdPosition(objectX, objectY); + if (specialPlantFieldData == null) + return false; + if (specialPlantStages[specialPlantFieldData.getSpecialPlantsIndex()] == 3) + return true; + return false; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/ToolLeprechaun.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/ToolLeprechaun.java new file mode 100644 index 00000000..d7d109e3 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/ToolLeprechaun.java @@ -0,0 +1,377 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.rebotted.game.content.skills.farming; + +/** + * + * @author ArrowzFtw + */ + +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.game.dialogues.ChatEmotes; +import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemData; +import com.rebotted.game.players.Player; + +/** + * Created by IntelliJ IDEA. User: vayken Date: 23/02/12 Time: 12:12 To change + * this template use File | Settings | File Templates. + */ + +public class ToolLeprechaun { + + private Player player; + + public ToolLeprechaun(Player player) { + this.player = player; + } + + public int[] tools = { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 };// new + // int[18]; + + /* setting up the store item array and the player item array */ + + public Item[] storeItems = { new Item(5341), new Item(5343), new Item(952), + new Item(5329), new Item(5331), new Item(5325) }; + public Item[] storeItems2 = { new Item(1925), new Item(6032), + new Item(6034) }; + public Item[] storeItemsClient = { new Item(5341), new Item(5343), + new Item(952), new Item(5329), new Item(5331), new Item(5325) }; + public Item[] storeItems2Client = { new Item(1925), new Item(6032), + new Item(6034) }; + + /* setting up the main constant field */ + + public static final int[] NOTABLE_ITEMS = { 225, 239, 247, 249, 251, 253, + 255, 257, 259, 261, 263, 265, 267, 269, 3000, 2481, 592, 1965, + 1967, 6004, 5980, 5976, 1955, 1963, 2108, 5972, 2114, 754, 2126, + 248, 1951, 240, 2367, 1942, 1957, 1965, 1982, 5986, 5504, 5982, + 6006, 5994, 5996, 5931, 5998, 6000, 6002, 6016, 6055 }; + + public static final int LEPRECHAUN_INTERFACE = 15614; + public static final int LEPRECHAUN_INTERFACE_CONTAINER = 15682;// + public static final int LEPRECHAUN_INTERFACE_CONTAINER2 = 15683;// + public static final int PLAYER_INTERFACE = 15593; + public static final int PLAYER_INTERFACE_CONTAINER = 15594;// + public static final int PLAYER_INTERFACE_CONTAINER2 = 15595;// + public static final int TOOL_CONFIGS = 615; + + /* this enum store every tool data for the interfaces loading */ + + public enum ToolStoreData { + + RAKE(0, 5341, 1, 1, 15596, 15597, "Rake"), SEED_DIBBER(1, 5343, 2, 1, + 15598, 15599, "Dibber"), SPADE(2, 952, 4, 1, 15600, 15601, + "Spade"), SECATEURS(3, 5329, 8, 1, 15602, 15603, "Secateurs"), MAGIC_SECATEURS( + 4, 7409, 8, 1, 15602, 15603, "Secateurs"), WATERING_CAN_0(5, + 5331, 16, 1, 15604, 15605, "Watering Can"), WATERING_CAN_1(6, + 5333, 32, 1, 15604, 15605, "Watering Can"), WATERING_CAN_2(7, + 5334, 48, 1, 15604, 15605, "Watering Can"), WATERING_CAN_3(8, + 5335, 64, 1, 15604, 15605, "Watering Can"), WATERING_CAN_4(9, + 5336, 80, 1, 15604, 15605, "Watering Can"), WATERING_CAN_5(10, + 5337, 96, 1, 15604, 15605, "Watering Can"), WATERING_CAN_6(11, + 5338, 112, 1, 15604, 15605, "Watering Can"), WATERING_CAN_7(12, + 5339, 128, 1, 15604, 15605, "Watering Can"), WATERING_CAN_8(13, + 5340, 144, 1, 15604, 15605, "Watering Can"), GARDENING_TROWEL( + 14, 5325, 256, 1, 15606, 15607, "Trowel"), EMPTY_BUCKETS(15, + 1925, 512, 31, 15608, 15609, "Buckets"), COMPOST(16, 6032, + 16384, 255, 15610, 15611, "Compost"), SUPER_COMPOST(17, 6034, + 4194304, 255, 15612, 15613, "Super Compost"); + + private int toolIndex; + private int toolId; + private int toolConfig; + private int toolMaxQuantity; + private int toolFrameId; + private int toolCountFrameId; + private String toolName; + + private static Map tools = new HashMap(); + private static Map indexes = new HashMap(); + + public static ToolStoreData forId(int toolId) { + return tools.get(toolId); + } + + public static ToolStoreData forIndex(int index) { + return indexes.get(index); + } + + static { + for (ToolStoreData data : ToolStoreData.values()) { + tools.put(data.toolId, data); + indexes.put(data.toolIndex, data); + } + } + + ToolStoreData(int toolIndex, int toolId, int toolConfig, + int toolMaxQuantity, int toolFrameId, int toolCountFrameId, + String toolName) { + this.toolIndex = toolIndex; + this.toolId = toolId; + this.toolConfig = toolConfig; + this.toolMaxQuantity = toolMaxQuantity; + this.toolFrameId = toolFrameId; + this.toolCountFrameId = toolCountFrameId; + this.toolName = toolName; + } + + public int getToolIndex() { + return toolIndex; + } + + public int getToolId() { + return toolId; + } + + public int getToolConfig() { + return toolConfig; + } + + public int getToolMaxQuantity() { + return toolMaxQuantity; + } + + public int getToolFrameId() { + return toolFrameId; + } + + public int getToolCountFrameId() { + return toolCountFrameId; + } + + public String getToolName() { + return toolName; + } + } + + /* loading the interfaces */ + + public void loadInterfaces() { + player.getPacketSender().showInterface(LEPRECHAUN_INTERFACE); + player.getPacketSender().sendUpdateItems(LEPRECHAUN_INTERFACE_CONTAINER, storeItems); + player.getPacketSender().sendUpdateItems(LEPRECHAUN_INTERFACE_CONTAINER2, + storeItems2); + player.getPacketSender().setSidebarInterface(3, PLAYER_INTERFACE); + player.getPacketSender().sendUpdateItems(PLAYER_INTERFACE_CONTAINER, + storeItemsClient); + player.getPacketSender().sendUpdateItems(PLAYER_INTERFACE_CONTAINER2, + storeItems2Client); + updateStore(); + } + + /* handling watering can things */ + + public void handleAdditionalTools() { + int item; + int i = 5340; + while (!player.getItemAssistant().playerHasItem(i) + && i >= 5330) { + i--; + } + item = i; + if (item == 5330) { + return; + } + storeItemsClient[4] = new Item(item); + + if (player.getItemAssistant().playerHasItem(7409)) { + storeItemsClient[3] = new Item(7409); + } else { + storeItemsClient[3] = new Item(5329); + } + + } + + public void checkWateringCanQuantity() { + int counter = 0; + int counter2 = 0; + for (int i = 5; i <= 13; i++) { + ToolStoreData toolStoreData = ToolStoreData.forIndex(i); + if (player.getItemAssistant().playerHasItem(toolStoreData.getToolId())) { + counter2++; + } + if (tools[i] == 1) { + counter++; + } + } + if (counter == 0) { + storeItems[4] = new Item(5331); + } + if (counter2 == 0) { + storeItemsClient[4] = new Item(5331); + } + + } + + public boolean hasWateringCanInStore() { + int counter = 0; + for (int i = 5; i <= 13; i++) { + if (tools[i] == 1) { + counter++; + } + } + if (counter == 0) { + return false; + } + return true; + + } + + /* updating the store state and player state */ + + public void updateStore() { + int configValue = 0; + for (int i = 0; i < tools.length; i++) { + ToolStoreData toolStoreData = ToolStoreData.forIndex(i); + if (toolStoreData == null) { + return; + } + configValue += toolStoreData.getToolConfig() * tools[i]; + updateClientInterface(toolStoreData, player.getItemAssistant() + .getItemAmount(toolStoreData.getToolId()), i); + if (toolStoreData.getToolId() != 5332 + && toolStoreData.getToolId() >= 5331 + && toolStoreData.getToolId() <= 5340 && tools[i] == 1) { + storeItems[4] = new Item(toolStoreData.getToolId()); + } + if (toolStoreData.getToolId() == 7409 && tools[i] == 1) { + storeItems[3] = new Item(7409); + } + + } + handleAdditionalTools(); + checkWateringCanQuantity(); + player.getPacketSender().sendConfig(TOOL_CONFIGS, configValue); + player.getPacketSender().sendUpdateItems(LEPRECHAUN_INTERFACE_CONTAINER, + storeItems); + player.getPacketSender().sendUpdateItems(PLAYER_INTERFACE_CONTAINER, + storeItemsClient); + + } + + public void updateClientInterface(ToolStoreData toolStoreData, int count, + int index) { + player.tempBoolean = false; + if (count > 0) { + if (index >= 5 && index <= 13) { + player.tempBoolean = true; + } + player.getPacketSender().sendFrame126("@gre@" + toolStoreData.getToolName(), + toolStoreData.getToolFrameId()); + player.getPacketSender().sendFrame126("@gre@" + count, + toolStoreData.getToolCountFrameId()); + } else { + // watering can doses + if (index >= 5 && index <= 13 && player.tempBoolean) { + return; + } + // secateurs + if ((index == 3 || index == 4) + && (player.getItemAssistant().playerHasItem(7409) || player + .getItemAssistant().playerHasItem(5329))) { + return; + } + + player.getPacketSender().sendFrame126("" + toolStoreData.getToolName(), + toolStoreData.getToolFrameId()); + player.getPacketSender().sendFrame126("" + count, + toolStoreData.getToolCountFrameId()); + + } + } + + /* store any item with id and amount provided */ + + public void storeItems(int itemId, int amount) { + ToolStoreData toolStoreData = ToolStoreData.forId(itemId); + if (toolStoreData == null) { + return; + } + + int storeAmount = tools[toolStoreData.getToolIndex()]; + int finalAmount = amount; + if (!player.getItemAssistant().playerHasItem(itemId)) + return; + if (toolStoreData.getToolMaxQuantity() == storeAmount + || (itemId == 7409 || itemId == 5329) + && (tools[3] == 1 || tools[4] == 1) || hasWateringCanInStore() + && toolStoreData.getToolId() != 5332 && itemId >= 5340 + && itemId <= 5331) { + player.getPacketSender().sendMessage("You can't store any more of those."); + return; + } + if (player.getItemAssistant().getItemCount(itemId) <= 0) { + player.getPacketSender().sendMessage("You aren't carrying any of those."); + return; + } + if (player.getItemAssistant().getItemCount(itemId) < amount) { + finalAmount = player.getItemAssistant().getItemCount(itemId); + } + + player.getItemAssistant().deleteItem(itemId, finalAmount); + tools[toolStoreData.getToolIndex()] += finalAmount; + updateStore(); + + } + + /* withdraw any item with item id and amount provided */ + + public void withdrawItems(int itemId, int amount) { + ToolStoreData toolStoreData = ToolStoreData.forId(itemId); + if (toolStoreData == null) { + return; + } + + if (player.getItemAssistant().freeSlots() <= 0) { + player.getPacketSender().sendMessage("Not enough space in your inventory."); + return; + } + if (tools[toolStoreData.getToolIndex()] <= 0) { + player.getPacketSender().sendMessage( + "You haven't got any of those stored in here."); + return; + } + int finalAmount; + if (amount > tools[toolStoreData.getToolIndex()]) { + finalAmount = tools[toolStoreData.getToolIndex()]; + } else { + finalAmount = amount; + } + if (finalAmount > player.getItemAssistant().freeSlots() ) { + finalAmount = player.getItemAssistant().freeSlots() ; + } + + tools[toolStoreData.getToolIndex()] -= finalAmount; + player.getItemAssistant().addItem(itemId, finalAmount); + updateStore(); + } + + /* note any item with the item id provided */ + + public boolean noteItem(int itemId) { + + if (ItemData.itemIsNote[itemId]) { + player.getDialogueHandler().sendNpcChat(3021, ChatEmotes.DEFAULT, "That is a banknote!"); + return true; + } + for (int item : NOTABLE_ITEMS) { + if (itemId == item) { + int count = player.getItemAssistant().getItemAmount(itemId); + player.getItemAssistant().deleteItem(itemId, count); + player.getItemAssistant().addItem(itemId + 1, count); + player.getDialogueHandler().sendStatement( + "The tool leprechaun notes those items for you."); + + return true; + } + } + player.getDialogueHandler().sendNpcChat(3021, ChatEmotes.DEFAULT, "Nay, I've got no banknotes to exchange for that item."); + return true; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/WoodTrees.java b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/WoodTrees.java new file mode 100644 index 00000000..911016c7 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/content/skills/farming/WoodTrees.java @@ -0,0 +1,983 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.rebotted.game.content.skills.farming; + +/** + * + * @author ArrowzFtw + */ + +import java.awt.Point; +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.GameEngine; +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.content.skills.SkillConstants; +import com.rebotted.game.content.skills.SkillHandler; +import com.rebotted.game.content.skills.farming.ChopTree.Tree; +import com.rebotted.game.items.ItemAssistant; +import com.rebotted.game.players.Player; +import com.rebotted.util.Misc; + +/** + * Created by IntelliJ IDEA. User: vayken Date: 24/02/12 Time: 20:34 To change + * this template use File | Settings | File Templates. + */ +public class WoodTrees { + + private Player player; + + private static final double COMPOST_CHANCE = 0.9; + private static final double SUPERCOMPOST_CHANCE = 0.7; + private static final double CLEARING_EXPERIENCE = 4; + + public WoodTrees(Player player) { + this.player = player; + } + + // Farming data + public int[] treeStages = new int[4]; + public int[] treeSaplings = new int[4]; + public int[] treeHarvest = new int[4]; + public int[] treeState = new int[4]; + public long[] treeTimer = new long[4]; + public double[] diseaseChance = { 1, 1, 1, 1 }; + public boolean[] hasFullyGrown = { false, false, false, false }; + public boolean[] treeWatched = { false, false, false, false }; + + /* set of the constants for the patch */ + + // states - 2 bits plant - 6 bits + public static final int GROWING = 0x00; + public static final int DISEASED = 0x01; + public static final int DEAD = 0x02; + + public static final int MAIN_TREE_CONFIG = 502; + + /* This is the enum holding the saplings info */ + + public enum TreeData { + OAK(5370, 6043, 15, new int[] { 5968, 1 }, 160, 0.20, 14, 467.3, 0x08, + 0x0c, 0x0d, 0x0e, 1281), WILLOW(5371, 6045, 30, new int[] { + 5386, 1 }, 240, 0.20, 25, 1456.3, 0x0f, 0x15, 0x16, 0x17, 1308), MAPLE( + 5372, 6047, 45, new int[] { 5396, 1 }, 320, 0.25, 45, 3403.4, + 0x18, 0x20, 0x21, 0x22, 1307), YEW(5373, 6049, 60, new int[] { + 6016, 10 }, 400, 0.25, 81, 7069.9, 0x23, 0x2d, 0x2e, 0x2f, 1309), MAGIC( + 5374, 6051, 75, new int[] { 5976, 25 }, 480, 0.25, 145.5, + 13768.3, 0x30, 0x3c, 0x3d, 0x3e, 1292); + + private int saplingId; + private int rootsId; + private int levelRequired; + private int[] paymentToWatch; + private int growthTime; + private double diseaseChance; + private double plantingXp; + private double checkHealthXp; + private int startingState; + private int endingState; + private int chopDownState; + private int stumpState; + private int treeObjectAssociated; + + private static Map saplings = new HashMap(); + + static { + for (TreeData data : TreeData.values()) { + saplings.put(data.saplingId, data); + } + } + + TreeData(int saplingId, int rootsId, int levelRequired, + int[] paymentToWatch, int growthTime, double diseaseChance, + double plantingXp, double checkHealthXp, int startingState, + int endingState, int chopDownState, int stumpState, + int treeObjectAssociated) { + this.saplingId = saplingId; + this.rootsId = rootsId; + this.levelRequired = levelRequired; + this.paymentToWatch = paymentToWatch; + this.growthTime = growthTime; + this.diseaseChance = diseaseChance; + this.plantingXp = plantingXp; + this.checkHealthXp = checkHealthXp; + this.startingState = startingState; + this.endingState = endingState; + this.chopDownState = chopDownState; + this.stumpState = stumpState; + this.treeObjectAssociated = treeObjectAssociated; + } + + public static TreeData forId(int saplingId) { + return saplings.get(saplingId); + } + + public int getSaplingId() { + return saplingId; + } + + public int getRootsId() { + return rootsId; + } + + public int getLevelRequired() { + return levelRequired; + } + + public int[] getPaymentToWatch() { + return paymentToWatch; + } + + public int getGrowthTime() { + return growthTime; + } + + public double getDiseaseChance() { + return diseaseChance; + } + + public double getPlantingXp() { + return plantingXp; + } + + public double getCheckHealthXp() { + return checkHealthXp; + } + + public int getStartingState() { + return startingState; + } + + public int getEndingState() { + return endingState; + } + + public int getChopDownState() { + return chopDownState; + } + + public int getStumpState() { + return stumpState; + } + + public int getTreeObjectAssociated() { + return treeObjectAssociated; + } + } + + /* This is the enum data about the different patches */ + + public enum TreeFieldsData { + VARROCK(0, + new Point[] { new Point(3228, 3458), new Point(3230, 3460) }, + 2341), LUMBRIDGE(1, new Point[] { new Point(3192, 3230), + new Point(3194, 3232) }, 2342), TAVERLEY(2, new Point[] { + new Point(2935, 3437), new Point(2937, 3439) }, 2339), FALADOR( + 3, + new Point[] { new Point(3003, 3372), new Point(3005, 3374) }, + 2340); + + private int treeIndex; + private Point[] treePosition; + private int npcId; + + private static Map npcsProtecting = new HashMap(); + + static { + for (TreeFieldsData data : TreeFieldsData.values()) { + npcsProtecting.put(data.npcId, data); + + } + } + + public static TreeFieldsData forId(int npcId) { + return npcsProtecting.get(npcId); + } + + TreeFieldsData(int treeIndex, Point[] treePosition, int npcId) { + this.treeIndex = treeIndex; + this.treePosition = treePosition; + this.npcId = npcId; + } + + public static TreeFieldsData forIdPosition(int x, int y) { + for (TreeFieldsData treeFieldsData : TreeFieldsData.values()) { + if (FarmingConstants.inRangeArea( + treeFieldsData.getTreePosition()[0], + treeFieldsData.getTreePosition()[1], x, y)) { + return treeFieldsData; + } + } + return null; + } + + public int getTreeIndex() { + return treeIndex; + } + + public Point[] getTreePosition() { + return treePosition; + } + + public int getNpcId() { + return npcId; + } + } + + /* This is the enum that hold the different data for inspecting the plant */ + + public enum InspectData { + OAK(5370, new String[][] { + { "The acorn sapling has only just been planted." }, + { "The acorn sapling grows larger." }, + { "The oak tree produces a small canopy." }, + { "The oak tree grows larger." }, + { "The oak tree is ready to harvest." } }), WILLOW(5371, + new String[][] { + { "The willow sapling has only just been planted." }, + { "The willow sapling grows a few small branches." }, + { "The willow tree develops a small canopy." }, + { "The willow tree trunk becomes dark brown,", + "and the canopy grows." }, + { "The trunk thickens, and the canopy grows", + "yet larger." }, + { "The willow tree is fully grown." } }), MAPLE(5372, + new String[][] { + { "The maple sapling has only just been planted." }, + { "The mapling sapling grows a few small branches." }, + { "The maple tree develops a small canopy." }, + { "The maple tree trunk straightens and the canopy", + "grows larger." }, + { "The maple tree canopy grows." }, + { "The maple tree grows." }, + { "The maple tree is ready to be harvested." } }), YEW( + 5373, new String[][] { + { "The yew sapling has only just been planted." }, + { "The yew sapling grows a few small branches." }, + { "The yew tree develops several small canopies." }, + { "The yew tree trunk texture becomes smoother and", + "the canopies grow larger." }, + { "The yew tree grows larger." }, + { "The yew tree canopies become more angular and", + "cone shaped due to texture placement." }, + { "The yew tree gains a rougher tree bark texture and", + "the base becomes darker." }, + { "The yew tree base becomes light again, and the", + "trunk loses its texture." }, + { "The yew tree bark gains a stripy texture." }, + { "The yew tree is ready to be harvested." } }), MAGIC( + 5374, + new String[][] { + { "The magic sapling has only just been planted." }, + { "The magic sapling grows a little bit." }, + { "The magic sapling grows a little bit more." }, + { "The magic sapling grows a few small branches." }, + { "The magic tree grows a small canopy." }, + { "The magic tree canopy becomes larger, and", + "starts producing sparkles." }, + { "The magic tree grows and the base becomes lighter." }, + { "The magic tree grows and the base becomes darker." }, + { "The magic tree's bark is more prominent and the", + "canopy gains more sparkles." }, + { "The magic tree grows taller." }, + { "The magic tree grows taller." }, + { "The magic tree is ready to be harvested." } }); + + private int saplingId; + private String[][] messages; + + private static Map saplings = new HashMap(); + + static { + for (InspectData data : InspectData.values()) { + saplings.put(data.saplingId, data); + } + } + + InspectData(int saplingId, String[][] messages) { + this.saplingId = saplingId; + this.messages = messages; + } + + public static InspectData forId(int saplingId) { + return saplings.get(saplingId); + } + + public int getSaplingId() { + return saplingId; + } + + public String[][] getMessages() { + return messages; + } + } + + /* update all the patch states */ + + public void updateTreeStates() { + // varrock - lumbridge - taverley - falador + int[] configValues = new int[treeStages.length]; + + int configValue; + for (int i = 0; i < treeStages.length; i++) { + configValues[i] = getConfigValue(treeStages[i], treeSaplings[i], + treeState[i], i); + } + + configValue = (configValues[0] << 16) + (configValues[1] << 8 << 16) + + configValues[2] + (configValues[3] << 8); + player.getPacketSender().sendConfig(MAIN_TREE_CONFIG, configValue); + + } + + /* getting the different config values */ + + public int getConfigValue(int treeStage, int saplingId, int plantState, + int index) { + TreeData treeData = TreeData.forId(saplingId); + switch (treeStage) { + case 0:// weed + return (GROWING << 6) + 0x00; + case 1:// weed cleared + return (GROWING << 6) + 0x01; + case 2: + return (GROWING << 6) + 0x02; + case 3: + return (GROWING << 6) + 0x03; + } + if (treeData == null) { + return -1; + } + if (treeData.getEndingState() == treeData.getStartingState() + + treeStage - 1) { + hasFullyGrown[index] = true; + } + + if (plantState == 6) + return treeData.getChopDownState(); + if (plantState == 7) + return treeData.getStumpState(); + + return (getPlantState(plantState) << 6) + treeData.getStartingState() + + treeStage - 4; + } + + /* getting the plant states */ + + public int getPlantState(int plantState) { + switch (plantState) { + case 0: + return GROWING; + case 1: + return DISEASED; + case 2: + return DEAD; + } + return -1; + } + + /* calculating the disease chance and making the plant grow */ + + public void doCalculations() { + for (int i = 0; i < treeSaplings.length; i++) { + if (treeStages[i] > 0 && treeStages[i] <= 3 + && GameEngine.getMinutesCounter() - treeTimer[i] >= 5) { + treeStages[i]--; + treeTimer[i] = GameEngine.getMinutesCounter(); + updateTreeStates(); + continue; + } + TreeData treeData = TreeData.forId(treeSaplings[i]); + if (treeData == null) { + continue; + } + + long difference = GameEngine.getMinutesCounter() - treeTimer[i]; + long growth = treeData.getGrowthTime(); + int nbStates = treeData.getEndingState() + - treeData.getStartingState(); + int state = (int) (difference * nbStates / growth); + if (treeTimer[i] == 0 || treeState[i] == 2 || state > nbStates) { + continue; + } + if (4 + state != treeStages[i]) { + treeStages[i] = 4 + state; + if (treeStages[i] <= 4 + state) + for (int j = treeStages[i]; j <= 4 + state; j++) + doStateCalculation(i); + updateTreeStates(); + } + } + } + + public void modifyStage(int i) { + TreeData bushesData = TreeData.forId(treeSaplings[i]); + if (bushesData == null) + return; + long difference = GameEngine.getMinutesCounter() - treeTimer[i]; + long growth = bushesData.getGrowthTime(); + int nbStates = bushesData.getEndingState() + - bushesData.getStartingState(); + int state = (int) (difference * nbStates / growth); + treeStages[i] = 4 + state; + updateTreeStates(); + + } + + /* calculations about the diseasing chance */ + + public void doStateCalculation(int index) { + if (treeState[index] == 2) { + return; + } + // if the patch is diseased, it dies, if its watched by a farmer, it + // goes back to normal + if (treeState[index] == 1) { + if (treeWatched[index]) { + treeState[index] = 0; + TreeData treeData = TreeData.forId(treeSaplings[index]); + if (treeData == null) + return; + int difference = treeData.getEndingState() + - treeData.getStartingState(); + int growth = treeData.getGrowthTime(); + treeTimer[index] += (growth / difference); + modifyStage(index); + } else { + treeState[index] = 2; + } + } + + if (treeState[index] == 5 && treeStages[index] != 3) { + treeState[index] = 0; + } + + if (treeState[index] == 0 && treeStages[index] >= 5 + && !hasFullyGrown[index]) { + TreeData treeData = TreeData.forId(treeSaplings[index]); + if (treeData == null) { + return; + } + + double chance = diseaseChance[index] * treeData.getDiseaseChance(); + int maxChance = (int) chance * 100; + if (Misc.random(100) <= maxChance) { + treeState[index] = 1; + } + } + } + + /* clearing the patch with a rake of a spade */ + + public boolean clearPatch(int objectX, int objectY, int itemId) { + final TreeFieldsData hopsFieldsData = TreeFieldsData.forIdPosition( + objectX, objectY); + int finalAnimation; + int finalDelay; + if (hopsFieldsData == null + || (itemId != FarmingConstants.RAKE && itemId != FarmingConstants.SPADE)) { + return false; + } + + if (treeStages[hopsFieldsData.getTreeIndex()] == 3) { + return true; + } + if (treeStages[hopsFieldsData.getTreeIndex()] <= 3) { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.RAKE)) { + player.getDialogueHandler().sendStatement( + "You need a rake to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.RAKING_ANIM; + finalDelay = 5; + } + } else { + if (!player.getItemAssistant().playerHasItem(FarmingConstants.SPADE)) { + player.getDialogueHandler().sendStatement( + "You need a spade to clear this path."); + return true; + } else { + finalAnimation = FarmingConstants.SPADE_ANIM; + finalDelay = 3; + } + } + final int animation = finalAnimation; + player.stopPlayer(true); + player.startAnimation(animation); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.startAnimation(animation); + if (treeStages[hopsFieldsData.getTreeIndex()] <= 2) { + treeStages[hopsFieldsData.getTreeIndex()]++; + player.getItemAssistant().addItem(6055, 1); + } else { + treeStages[hopsFieldsData.getTreeIndex()] = 3; + container.stop(); + } + player.getPlayerAssistant().addSkillXP(CLEARING_EXPERIENCE, SkillConstants.FARMING.ordinal()); + treeTimer[hopsFieldsData.getTreeIndex()] = GameEngine + .getMinutesCounter(); + updateTreeStates(); + if (treeStages[hopsFieldsData.getTreeIndex()] == 3) { + container.stop(); + return; + } + } + + @Override + public void stop() { + resetTrees(hopsFieldsData.getTreeIndex()); + player.getPacketSender().sendMessage("You clear the patch."); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, finalDelay); + return true; + + } + + /* planting the saplings */ + + public boolean plantSapling(int objectX, int objectY, final int saplingId) { + final TreeFieldsData treeFieldsData = TreeFieldsData.forIdPosition( + objectX, objectY); + final TreeData treeData = TreeData.forId(saplingId); + if (treeFieldsData == null || treeData == null) { + return false; + } + + if (treeStages[treeFieldsData.getTreeIndex()] != 3) { + player.getPacketSender().sendMessage("You can't plant a sapling here."); + return true; + } + if (treeData.getLevelRequired() > player.playerLevel[SkillConstants.FARMING.ordinal()]) { + player.getDialogueHandler().sendStatement("You need a farming level of " + + treeData.getLevelRequired() + + " to plant this sapling."); + return true; + } + + if (!player.getItemAssistant().playerHasItem(FarmingConstants.TROWEL)) { + player.getDialogueHandler().sendStatement( + "You need a trowel to plant the sapling here."); + return true; + } + player.startAnimation( + FarmingConstants.PLANTING_POT_ANIM); + treeStages[treeFieldsData.getTreeIndex()] = 4; + player.getItemAssistant().deleteItem(saplingId, 1); + + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + treeState[treeFieldsData.getTreeIndex()] = 0; + treeSaplings[treeFieldsData.getTreeIndex()] = saplingId; + treeTimer[treeFieldsData.getTreeIndex()] = GameEngine + .getMinutesCounter(); + player.getPlayerAssistant().addSkillXP(treeData.getPlantingXp(), SkillConstants.FARMING.ordinal()); + container.stop(); + } + + @Override + public void stop() { + updateTreeStates(); + player.stopPlayer(false); + } + }, 3); + return true; + } + + @SuppressWarnings("unused") + private void displayAll() { + for (int i = 0; i < treeStages.length; i++) { + System.out.println("index : " + i); + System.out.println("state : " + treeState[i]); + System.out.println("harvest : " + treeHarvest[i]); + System.out.println("saplings : " + treeSaplings[i]); + System.out.println("level : " + treeStages[i]); + System.out.println("timer : " + treeTimer[i]); + System.out.println("disease chance : " + diseaseChance[i]); + System.out + .println("-----------------------------------------------------------------"); + } + } + + /* harvesting the plant resulted */ + + public boolean checkHealth(int objectX, int objectY) { + final TreeFieldsData treeFieldsData = TreeFieldsData.forIdPosition( + objectX, objectY); + if (treeFieldsData == null) { + return false; + } + final TreeData treeData = TreeData.forId(treeSaplings[treeFieldsData + .getTreeIndex()]); + if (treeData == null) { + return false; + } + + if (treeState[treeFieldsData.getTreeIndex()] != 0) + return false; + + player.startAnimation(832); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + player.getPacketSender() + .sendMessage( + "You examine the tree for signs of disease and find that it is in perfect health"); + player.getPlayerAssistant().addSkillXP(treeData.getCheckHealthXp(), SkillConstants.FARMING.ordinal()); + treeState[treeFieldsData.getTreeIndex()] = 6; + container.stop(); + } + + @Override + public void stop() { + updateTreeStates(); + } + }, 2); + return true; + } + + public void respawnStumpTimer(final int index) { + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + if (treeState[index] == 7) + treeState[index] = 6; + container.stop(); + } + + @Override + public void stop() { + } + }, 500); + } + + /* putting compost onto the plant */ + + public boolean putCompost(int objectX, int objectY, final int itemId) { + if (itemId != 6032 && itemId != 6034) { + return false; + } + final TreeFieldsData treeFieldsData = TreeFieldsData.forIdPosition( + objectX, objectY); + if (treeFieldsData == null) { + return false; + } + + if (treeStages[treeFieldsData.getTreeIndex()] != 3 + || treeState[treeFieldsData.getTreeIndex()] == 5) { + player.getPacketSender().sendMessage("This patch doesn't need compost."); + return true; + } + player.getItemAssistant().deleteItem(itemId, 1); + player.getItemAssistant().addItem(1925, 1); + + player.getPacketSender().sendMessage( + "You pour some " + (itemId == 6034 ? "super" : "") + + "compost on the patch."); + player.startAnimation(FarmingConstants.PUTTING_COMPOST); + player.getPlayerAssistant().addSkillXP(itemId == 6034 ? Compost.SUPER_COMPOST_EXP_USE + : Compost.COMPOST_EXP_USE, SkillConstants.FARMING.ordinal()); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + + diseaseChance[treeFieldsData.getTreeIndex()] *= itemId == 6032 ? COMPOST_CHANCE + : SUPERCOMPOST_CHANCE; + treeState[treeFieldsData.getTreeIndex()] = 5; + container.stop(); + } + + @Override + public void stop() { + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 7); + return true; + } + + /* inspecting a plant */ + + public boolean inspect(int objectX, int objectY) { + final TreeFieldsData treeFieldsData = TreeFieldsData.forIdPosition( + objectX, objectY); + if (treeFieldsData == null) { + return false; + } + + final InspectData inspectData = InspectData + .forId(treeSaplings[treeFieldsData.getTreeIndex()]); + final TreeData treeData = TreeData.forId(treeSaplings[treeFieldsData + .getTreeIndex()]); + if (treeState[treeFieldsData.getTreeIndex()] == 1) { + player.getDialogueHandler().sendStatement( + "This tree is diseased. Use secateurs to prune the area, ", + "or clear the patch with a spade."); + return true; + } else if (treeState[treeFieldsData.getTreeIndex()] == 2) { + player.getDialogueHandler().sendStatement("This tree is dead. You did not cure it while it was diseased.", + "Clear the patch with a spade."); + return true; + } else if (treeState[treeFieldsData.getTreeIndex()] == 6) { + player.getDialogueHandler().sendStatement( + "This is a tree stump, to remove it, use a spade on it", + "to recieve some roots and clear the patch."); + return true; + } + if (treeStages[treeFieldsData.getTreeIndex()] == 0) { + player.getDialogueHandler().sendStatement( + "This is a tree patch. The soil has not been treated.", + "The patch needs weeding."); + } else if (treeStages[treeFieldsData.getTreeIndex()] == 3) { + player.getDialogueHandler().sendStatement( + "This is a tree patch. The soil has not been treated.", + "The patch is empty and weeded."); + } else if (inspectData != null && treeData != null) { + player.getPacketSender().sendMessage( + "You bend down and start to inspect the patch..."); + + player.startAnimation(1331); + player.stopPlayer(true); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + + if (treeStages[treeFieldsData.getTreeIndex()] - 4 < inspectData + .getMessages().length - 2) { + player.getDialogueHandler().sendStatement( inspectData + .getMessages()[treeStages[treeFieldsData + .getTreeIndex()] - 4]); + } else if (treeStages[treeFieldsData.getTreeIndex()] < treeData + .getEndingState() - treeData.getStartingState() + 2) { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 2]); + } else { + player.getDialogueHandler().sendStatement( + inspectData.getMessages()[inspectData + .getMessages().length - 1]); + } + container.stop(); + } + + @Override + public void stop() { + player.startAnimation(1332); + player.stopPlayer(false); + // player.reset(); + } + }, 5); + } + return true; + } + + /* opening the corresponding guide about the patch */ + + public boolean guide(int objectX, int objectY) { + final TreeFieldsData treeFieldsData = TreeFieldsData.forIdPosition( + objectX, objectY); + if (treeFieldsData == null) { + return false; + } + + return true; + } + + /* Curing the plant */ + + public boolean pruneArea(int objectX, int objectY, int itemId) { + final TreeFieldsData treeFieldsData = TreeFieldsData.forIdPosition( + objectX, objectY); + if (treeFieldsData == null + || (itemId != FarmingConstants.SECATEURS && itemId != FarmingConstants.MAGIC_SECATEURS)) { + return false; + } + final TreeData treeData = TreeData.forId(treeSaplings[treeFieldsData + .getTreeIndex()]); + if (treeData == null) { + return false; + } + + if (treeState[treeFieldsData.getTreeIndex()] != 1) { + player.getPacketSender().sendMessage("This area doesn't need to be pruned."); + return true; + } + player.startAnimation(FarmingConstants.PRUNING_ANIM); + player.stopPlayer(true); + treeState[treeFieldsData.getTreeIndex()] = 0; + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + @Override + public void execute(CycleEventContainer container) { + + player.getPacketSender().sendMessage( + "You prune the area with your secateurs."); + container.stop(); + } + + @Override + public void stop() { + updateTreeStates(); + player.stopPlayer(false); + player.getPlayerAssistant().resetAnimation(); + } + }, 15); + + return true; + + } + + public void resetTrees(int index) { + treeSaplings[index] = 0; + treeState[index] = 0; + diseaseChance[index] = 1; + treeHarvest[index] = 0; + hasFullyGrown[index] = false; + treeWatched[index] = false; + } + + /** + * Woodcutting action + * + * @param = tree id + * @param x + * = tree x location + * @param y + * = tree y location + * @return + */ + + public boolean cut(final int x, final int y) { + + final TreeFieldsData treeFieldsData = TreeFieldsData + .forIdPosition(x, y); + if (treeFieldsData == null) + return false; + final TreeData treeData = TreeData.forId(treeSaplings[treeFieldsData + .getTreeIndex()]); + if (treeData == null) + return false; + + if (player.getItemAssistant().freeSlots() <= 0) { + player.getPacketSender().sendMessage("Not enough space in your inventory."); + return true; + } + + if (ChopTree.getAxe(player) == null) { + player.getPacketSender() + .sendMessage( + "You do not have an axe which you have the woodcutting level to use."); + return true; + } + + final int object = treeData.getTreeObjectAssociated(); + player.getPacketSender().sendMessage("You swing your axe at the tree."); + final int emoteId = ChopTree.getAxe(player).getAnimation(); + final int axeChance = ChopTree.getAxe(player).getBonus(); + final int treeLevel = ChopTree.getTree(object).getLevel(); + player.startAnimation(emoteId); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + final Tree tree = ChopTree.getTree(object); + @Override + public void execute(CycleEventContainer container) { + if (player.getItemAssistant().freeSlots() <= 0) { + container.stop(); + return; + } + + player.startAnimation(emoteId); + if (SkillHandler.skillCheck( + player.playerLevel[SkillConstants.WOODCUTTING.ordinal()], + treeLevel, axeChance * 20)) { + player.getItemAssistant().addItem(ChopTree.getTree(object).getLog(), 1); + player.getPacketSender().sendMessage( + "You get some " + + ItemAssistant + .getItemName(ChopTree.getTree(object) + .getLog()) + .toLowerCase() + "."); + player.getPlayerAssistant().addSkillXP(ChopTree.getTree(object).getXP(), SkillConstants.WOODCUTTING.ordinal()); + if (Misc.random(100) <= tree.getDecayChance()) { + respawnStumpTimer(treeFieldsData.getTreeIndex()); + treeState[treeFieldsData.getTreeIndex()] = 7; + updateTreeStates(); + container.stop(); + player.startAnimation(-1, 0); + } + } + if (!canCut(x, y)) { + player.startAnimation(-1, 0); + container.stop(); + } + } + @Override + public void stop() { + // TODO Auto-generated method stub + + } + }, 4); + return true; + } + + /** + * Checks if you can chop the tree + * + * @param = tree id + * @param x + * = tree x location + * @param y + * = tree y location + * @return if can cut + */ + public boolean canCut(final int x, final int y) { + final TreeFieldsData treeFieldsData = TreeFieldsData + .forIdPosition(x, y); + if (treeFieldsData == null) + return false; + final TreeData treeData = TreeData.forId(treeSaplings[treeFieldsData + .getTreeIndex()]); + if (treeData == null) + return false; + final int object = treeData.getTreeObjectAssociated(); + + if (!hasFullyGrown[treeFieldsData.getTreeIndex()]) { + return false; + } + if (ChopTree.getAxe(player) == null) { + player.getPacketSender() + .sendMessage( + "You do not have an axe which you have the woodcutting level to use."); + return false; + } + if (player.getItemAssistant().freeSlots() <= 0) { + return false; + } + if (!SkillHandler.hasRequiredLevel(player, SkillConstants.WOODCUTTING.ordinal(), ChopTree + .getTree(object).getLevel(), "chop this tree")) { + return false; + } + return true; + } + + /* checking if the patch is raked */ + + public boolean checkIfRaked(int objectX, int objectY) { + final TreeFieldsData treeFieldsData = TreeFieldsData.forIdPosition( + objectX, objectY); + if (treeFieldsData == null) + return false; + if (treeStages[treeFieldsData.getTreeIndex()] == 3) + return true; + return false; + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/dialogues/DialogueHandler.java b/2006Redone Server/src/main/java/com/rebotted/game/dialogues/DialogueHandler.java index 2e282b58..a5e1320d 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/dialogues/DialogueHandler.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/dialogues/DialogueHandler.java @@ -7,6 +7,7 @@ import com.rebotted.game.content.quests.QuestRewards; import com.rebotted.game.content.randomevents.FreakyForester; import com.rebotted.game.content.randomevents.RandomEventHandler; import com.rebotted.game.content.skills.SkillHandler; +import com.rebotted.game.content.skills.farming.Farmers; import com.rebotted.game.content.skills.slayer.Slayer; import com.rebotted.game.content.traveling.Sailing; import com.rebotted.game.globalworldobjects.PassDoor; @@ -24,9 +25,15 @@ public class DialogueHandler { public DialogueHandler(Player player2) { this.player = player2; } + + public void endDialogue() { + player.nextChat = 0; + player.dialogueAction = 0; + } public void sendDialogues(int dialogue, int npcId) { int MOLE_SKIN = player.getItemAssistant().getItemCount(7418), MOLE_CLAW = player.getItemAssistant().getItemCount(7416); + Farmers.FarmersData farmersData = Farmers.FarmersData.forId(player.npcType); player.talkingNpc = npcId; switch (dialogue) { case 0: @@ -4079,7 +4086,7 @@ public class DialogueHandler { break; /* - * case 1028: client.getDialogues().sendStatement( + * case 1028: client.getDialogueHandlers().sendStatement( * "10 coins are removed from your inventory."); client.nextChat = 0; * break; */ @@ -6936,6 +6943,107 @@ public class DialogueHandler { QuestRewards.blackKnightReward(player); player.nextChat = 0; break; + + case 3530://1 + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.DEFAULT, "Hey, I am one of the master farmers of this world but", "you can call me " + NpcHandler.getNpcListName(player.npcType) + ". So, what do you need from me?"); + if (farmersData.getFieldProtected() == "tree") + player.nextChat = 3531; + else + player.nextChat = 3532; + break; + case 3531://2 + player.getDialogueHandler().sendOption("Would you chop my tree down for me?", "Could you take care of my crops for me?", "Can you give me any farming advice?", "Can you sell me something?", "That's all, thanks"); + player.dialogueAction = 112; + break; + case 3532://3 + player.getDialogueHandler().sendOption("Could you take care of my crops for me?", "Can you give me any farming advice?", "Can you sell me something?", "That's all, thanks"); + player.dialogueAction = 113; + break; + case 3533://4 + player.getDialogueHandler().sendPlayerChat(ChatEmotes.DEFAULT, "Would you chop my tree down for me?"); + player.nextChat = 3534; + break; + case 3534://5 + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.DEFAULT, "Sure, for only 200gp, I will chop it down for you"); + player.nextChat = 3536; + break; + case 3535://6 + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.DEFAULT, "Sorry, but you have no tree growing in this patch."); + player.getDialogueHandler().endDialogue(); + break; + case 3536://7 + player.getDialogueHandler().sendOption("Sure, here you go", "Sorry, I am a little broke."); + player.dialogueAction = 114; + break; + case 3537://8 + player.getDialogueHandler().sendPlayerChat(ChatEmotes.DEFAULT, "Sure, Here you go"); + player.nextChat = 3539; + break; + case 3538://9 + player.getDialogueHandler().sendPlayerChat(ChatEmotes.ANNOYED, "Sorry, I am a little broke"); + player.getDialogueHandler().endDialogue(); + break; + case 3539://10 + Farmers.chopDownTree(player, player.npcType); + break; + case 3540://11 + player.getDialogueHandler().sendPlayerChat(ChatEmotes.DEFAULT, "Could you take care of my crops for me?"); + if (farmersData.getFieldProtected() == "allotment") + player.nextChat = 3541; + else + player.nextChat = 3543; + break; + case 3541://12 + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.HAPPY_JOYFUL, "I Might, Which one were you thinking of?"); + player.nextChat = 3542; + break; + case 3542://13 + player.getDialogueHandler().sendOption(farmersData.getDialogueHandlerOptions()); + player.dialogueAction = 115; + break; + case 3543://14 + Farmers.protectPlant(player, -1, farmersData.getFieldProtected(), player.npcType, 1); + break; + case 3544://15 + player.getDialogueHandler().sendOption("Sure, here you go.", "Sorry, I don't have those at the moment."); + player.dialogueAction = 116; + break; + case 3545://16 + player.getDialogueHandler().sendPlayerChat(ChatEmotes.DEFAULT, "Sure, here you go."); + player.nextChat = 3547; + break; + case 3546://17 + player.getDialogueHandler().sendPlayerChat(ChatEmotes.DEFAULT, "Sorry, I don't have those at the moment."); + player.getDialogueHandler().endDialogue(); + break; + case 3547://18 + Farmers.protectPlant(player, player.getTempInteger(), farmersData.getFieldProtected(), player.npcType, 2); + break; + case 3548://19 + player.getDialogueHandler().sendPlayerChat(ChatEmotes.DEFAULT, "Can you give me any farming advice?"); + player.nextChat = 3549; + break; + case 3549://20 + Farmers.sendFarmingAdvice(player); + player.getDialogueHandler().endDialogue(); + break; + case 3550://21 + player.getDialogueHandler().sendPlayerChat(ChatEmotes.DEFAULT, "Can you sell me something?"); + player.nextChat = 3551; + break; + case 3551://22 + player.getDialogueHandler().sendNpcChat(player.npcType, ChatEmotes.HAPPY_JOYFUL, "Sure, I have a bunch of tools for you to use."); + player.nextChat = 3552; + break; + case 3552://23 + player.getDialogueHandler().endDialogue(); + player.getPacketSender().closeAllWindows(); + player.getShopAssistant().openShop(farmersData.getShopId()); + break; + case 3553://24 + player.getDialogueHandler().sendPlayerChat(ChatEmotes.DEFAULT, "That's all, thanks"); + player.getDialogueHandler().endDialogue(); + break; } } @@ -7135,6 +7243,46 @@ public class DialogueHandler { /* * Npc Chatting */ + + public void sendNpcChat(int npcId, ChatEmotes e, String... line) { + String npcName = NpcHandler.getNpcListName(npcId).replaceAll("_", " "); + switch (line.length) { + case 1: + player.getPacketSender().sendDialogueAnimation(4883, getChatAnim(e)); + player.getPacketSender().sendFrame126(npcName, 4884); + player.getPacketSender().sendFrame126(line[0], 4885); + player.getPacketSender().sendNPCDialogueHead(npcId, 4883); + player.getPacketSender().sendChatInterface(4882); + break; + case 2: + player.getPacketSender().sendDialogueAnimation(4888, getChatAnim(e)); + player.getPacketSender().sendFrame126(npcName, 4889); + player.getPacketSender().sendFrame126(line[0], 4890); + player.getPacketSender().sendFrame126(line[1], 4891); + player.getPacketSender().sendNPCDialogueHead(npcId, 4888); + player.getPacketSender().sendChatInterface(4887); + break; + case 3: + player.getPacketSender().sendDialogueAnimation(4894, getChatAnim(e)); + player.getPacketSender().sendFrame126(npcName, 4895); + player.getPacketSender().sendFrame126(line[0], 4896); + player.getPacketSender().sendFrame126(line[1], 4897); + player.getPacketSender().sendFrame126(line[2], 4898); + player.getPacketSender().sendNPCDialogueHead(npcId, 4894); + player.getPacketSender().sendChatInterface(4893); + break; + case 4: + player.getPacketSender().sendDialogueAnimation(4901, getChatAnim(e)); + player.getPacketSender().sendFrame126(npcName, 4902); + player.getPacketSender().sendFrame126(line[0], 4903); + player.getPacketSender().sendFrame126(line[1], 4904); + player.getPacketSender().sendFrame126(line[2], 4905); + player.getPacketSender().sendFrame126(line[3], 4906); + player.getPacketSender().sendNPCDialogueHead(npcId, 4901); + player.getPacketSender().sendChatInterface(4900); + break; + } + } public void sendNpcChat1(String s, int ChatNpc, String name) { player.getPacketSender().sendDialogueAnimation(4883, 591); diff --git a/2006Redone Server/src/main/java/com/rebotted/game/dialogues/DialogueOptions.java b/2006Redone Server/src/main/java/com/rebotted/game/dialogues/DialogueOptions.java index 56ef7d11..6d619e6b 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/dialogues/DialogueOptions.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/dialogues/DialogueOptions.java @@ -14,6 +14,41 @@ public class DialogueOptions { public static void handleDialogueOptions(Player player, int buttonId) { switch (buttonId) { + case 9190: + switch (player.dialogueAction) { + case 112: + player.getDialogueHandler().sendDialogues(3533, player.npcType);//4 + break; + } + break; + case 9191: + switch (player.dialogueAction) { + case 112: + player.getDialogueHandler().sendDialogues(3540, player.npcType); + break; + } + break; + case 9192: + switch (player.dialogueAction) { + case 112: + player.getDialogueHandler().sendDialogues(3548, player.npcType); + break; + } + break; + case 9193: + switch (player.dialogueAction) { + case 112: + player.getDialogueHandler().sendDialogues(3550, player.npcType); + break; + } + break; + case 9194: + switch (player.dialogueAction) { + case 112: + player.getDialogueHandler().sendDialogues(3553, player.npcType); + break; + } + break; case 9157:// barrows tele to tunnels if (player.dialogueAction == 1) { int r = 4; @@ -59,8 +94,7 @@ public class DialogueOptions { player.getDialogueHandler().sendDialogues(361, player.npcType); return; } else if (player.dialogueAction == 50) { - player.getPlayerAssistant().startTeleport(2898, 3562, 0, - "modern"); + player.getPlayerAssistant().startTeleport(2898, 3562, 0, "modern"); Teles.necklaces(player); return; } else if (player.dialogueAction == 55) { @@ -118,6 +152,12 @@ public class DialogueOptions { } else if (player.dialogueAction == 93) { player.getDialogueHandler().sendDialogues(23, player.npcType); return; + } else if (player.dialogueAction == 114) { + player.getDialogueHandler().sendDialogues(3537, player.npcType); + return; + } else if (player.dialogueAction == 116) { + player.getDialogueHandler().sendDialogues(3545, player.npcType); + return; } else if (player.dialogueAction == 118) { player.getDialogueHandler().sendDialogues(394, player.npcType); return; @@ -321,6 +361,12 @@ public class DialogueOptions { } else if (player.dialogueAction == 91) { player.getDialogueHandler().sendDialogues(17, player.npcType); return; + } else if (player.dialogueAction == 114) { + player.getDialogueHandler().sendDialogues(3538, player.npcType); + return; + } else if (player.dialogueAction == 116) { + player.getDialogueHandler().sendDialogues(3546, player.npcType); + return; } else if (player.dialogueAction == 118) { player.getDialogueHandler().sendDialogues(392, player.npcType); return; @@ -503,10 +549,12 @@ public class DialogueOptions { player.getDialogueHandler().sendDialogues(378, player.npcType); } if (player.dialogueAction == 51) { - player.getPlayerAssistant().gloryTeleport(3088, 3500, 0, - "modern"); + player.getPlayerAssistant().gloryTeleport(3088, 3500, 0, "modern"); + Teles.necklaces(player); + } + if (player.dialogueAction == 113) { + player.getDialogueHandler().sendDialogues(3540, player.npcType); } - Teles.necklaces(player); if (player.dialogueAction == 52) { player.getDialogueHandler().sendDialogues(52, player.npcType); } @@ -543,6 +591,9 @@ public class DialogueOptions { if (player.dialogueAction == 2) { player.getPlayerAssistant().startTeleport(2884, 3395, 0, "modern"); } + if (player.dialogueAction == 113) { + player.getDialogueHandler().sendDialogues(3548, player.npcType); + } if (player.dialogueAction == 122 && player.objectId == 12163 || player.objectId == 12165 || player.objectId == 12166) {//champ player.getPlayerAssistant().startTeleport(3203, 3343, 0, "modern"); } else if (player.objectId == 12164) { @@ -571,8 +622,8 @@ public class DialogueOptions { } if (player.dialogueAction == 51) { player.getPlayerAssistant().gloryTeleport(3293, 3174, 0, "modern"); + Teles.necklaces(player); } - Teles.necklaces(player); if (player.dialogueAction == 52) { player.getDialogueHandler().sendDialogues(64, player.npcType); } @@ -612,6 +663,9 @@ public class DialogueOptions { if (player.dialogueAction == 69) { player.getDialogueHandler().sendDialogues(500003, player.npcType); } + if (player.dialogueAction == 113) { + player.getDialogueHandler().sendDialogues(3550, player.npcType); + } if (player.dialogueAction == 122 && player.objectId == 12164 || player.objectId == 12165 || player.objectId == 12166) {//lumby player.getPlayerAssistant().startTeleport(3243, 3237, 0, "modern"); } else if (player.objectId == 12163) { @@ -640,8 +694,8 @@ public class DialogueOptions { } if (player.dialogueAction == 51) { player.getPlayerAssistant().gloryTeleport(2911, 3152, 0, "modern"); + Teles.necklaces(player); } - Teles.necklaces(player); if (player.dialogueAction == 52) { player.getDialogueHandler().sendDialogues(65, player.npcType); } @@ -678,6 +732,9 @@ public class DialogueOptions { if (player.dialogueAction == 2) { player.getPlayerAssistant().startTeleport(2669, 3714, 0, "modern"); } + if (player.dialogueAction == 113) { + player.getDialogueHandler().sendDialogues(3553, player.npcType); + } if (player.dialogueAction == 69) { player.getDialogueHandler().sendDialogues(500004, player.npcType); } @@ -690,14 +747,12 @@ public class DialogueOptions { } } if (player.dialogueAction == 3) { - player.getPlayerAssistant().startTeleport(2540, 4716, 0, - "modern"); + player.getPlayerAssistant().startTeleport(2540, 4716, 0, "modern"); } if (player.dialogueAction == 51) { - player.getPlayerAssistant().gloryTeleport(3103, 3249, 0, - "modern"); + player.getPlayerAssistant().gloryTeleport(3103, 3249, 0, "modern"); + Teles.necklaces(player); } - Teles.necklaces(player); if (player.dialogueAction == 52) { player.getDialogueHandler().sendDialogues(63, player.npcType); } diff --git a/2006Redone Server/src/main/java/com/rebotted/game/items/GameItem.java b/2006Redone Server/src/main/java/com/rebotted/game/items/GameItem.java index 9b76f281..a6135d3b 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/items/GameItem.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/items/GameItem.java @@ -6,7 +6,7 @@ public class GameItem { public boolean stackable = false; public GameItem(int id, int amount) { - if (Item.itemStackable[id]) { + if (ItemData.itemStackable[id]) { stackable = true; } this.id = id; diff --git a/2006Redone Server/src/main/java/com/rebotted/game/items/Inventory.java b/2006Redone Server/src/main/java/com/rebotted/game/items/Inventory.java new file mode 100644 index 00000000..7bfe6a4d --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/items/Inventory.java @@ -0,0 +1,149 @@ +package com.rebotted.game.items; + +import com.rebotted.GameConstants; +import com.rebotted.GameEngine; +import com.rebotted.game.players.Player; + +/** + * + * @author ArrowzFtw + * @note itemId+1 is the playerItems + * @note playerItems-1 = normalItemId + */ +public class Inventory { + + Player player; + + public Inventory(Player player) { + this.player = player; + } + + public void removeItem(Item i) { + player.getItemAssistant().deleteItem(i.getId(), i.getCount()); + } + + public void addItemToSlot(Item i, int slot) { + if (get(slot) != i.getId() + 1) { + player.playerItems[slot] = i.getId() + 1; + player.playerItemsN[slot] = i.getCount(); + } else { + player.playerItemsN[slot] += i.getCount(); + } + update(); + } + + public int get(int slot) { + return player.playerItems[slot]; + } + + public void update() { + player.getItemAssistant().resetItems(3214); + } + + public boolean contains(int id) { + return player.getItemAssistant().playerHasItem(id); + } + + public boolean contains(Item item) { + return player.getItemAssistant().playerHasItem(item.getId(), item.getCount()); + } + + public boolean contains(int id, int amount) { + return player.getItemAssistant().playerHasItem(id, amount); + } + + public Inventory getItemContainer() { + return this; + } + + public void addItem(Item item) { + player.getItemAssistant().addItem(item.getId(), item.getCount()); + } + + public int getItemAmount(int id) { + return player.getItemAssistant().getItemAmount(id); + } + + public void replace(int item, int newItem) { + player.getItemAssistant().deleteItem(item, 1); + player.getItemAssistant().addItem(newItem, 1); + } + + public int getCount(int i) { + return player.getItemAssistant().getItemAmount(i); + } + + public void set(int slot, Item item) { + player.playerItems[slot] = item.getId() + 1; + player.playerItemsN[slot] = item.getCount(); + update(); + } + + public int freeSlots() { + return player.getItemAssistant().freeSlots(); + } + + public void add(int id) { + player.getItemAssistant().addItem(id, 1); + } + + public boolean add(int id, int amount) { + if (player.getItemAssistant().isStackable(id)) { + int allAmount = getStackedGroundAmount(id, amount, getCount(id)); + if (allAmount > 0) { + GameEngine.itemHandler.createGroundItem(player, id, player.getX(), player + .getY(), allAmount, player + .getId()); + player.getItemAssistant().deleteItem(id, Integer.MAX_VALUE); + player.getItemAssistant().addItem(id, Integer.MAX_VALUE); + return true; + } + } + return player.getItemAssistant().addItem(id, amount); + } + + public int getStackedGroundAmount(int itemId, int addItemAmount, + int itemAmount) { + long x = 0; + x += itemAmount; + x += addItemAmount; + if (x > 2147483647) { + x -= 2147483647; + return (int) x; + } + return -1; + } + + public boolean canAddItem(Item item) { + return item.getCount() <= freeSlots(); + } + + public void addItem(Item item, boolean drop) { + if (!drop) { + addItem(item); + } else { + GameEngine.itemHandler.createGroundItem(player, item.getId(), player.getX(), player.getY(), item.getCount(), player.playerId); + } + } + + public boolean ownsItem(String itemName) { + for (int i = 0; i < GameConstants.ITEM_LIMIT; i++) { + if (GameEngine.itemHandler.ItemList[i] != null) { + if (GameEngine.itemHandler.ItemList[i].itemName + .equalsIgnoreCase(itemName)) { + return true; + } + } + } + return false; + } + + public boolean playerHasItem(int item) { + return player.getItemAssistant().playerHasItem(item); + } + + public void removeItemSlot(Item item, int slot) { + player.getItemAssistant().deleteItem(item.getId(), slot, item.getCount()); + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/items/Item.java b/2006Redone Server/src/main/java/com/rebotted/game/items/Item.java index 338ff631..45dbd32f 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/items/Item.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/items/Item.java @@ -1,376 +1,105 @@ package com.rebotted.game.items; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -import com.rebotted.GameConstants; import com.rebotted.GameEngine; +/** + * Represents a single item. + * + * @author Graham Edgecombe + * + */ public class Item { - public static int capes[] = { 2731, 2677, 2683, 2680, 2701, 2686, 2689, - 2692, 2737, 2734, 2716, 2728, 2695, 2713, 2725, 2722, 2707, 2704, - 2710, 2719, 2737, 2698, 14590, 2701, 8102, 8075, 8044, 8045, 8042, - 8043, 8037, 8038, 8025, 8026, 8018, 7858, 7994, 7983, 7984, 7985, - 7986, 7987, 7982, 7978, 3781, 3783, 3785, 3787, 3789, 3777, 3779, - 3759, 3761, 3763, 3765, 6111, 6570, 6568, 1007, 1019, 1021, 1023, - 1027, 1029, 1031, 1052, 2412, 2413, 2414, 4304, 4315, 4317, 4319, - 4321, 4323, 4325, 4327, 4329, 4331, 4333, 4335, 4337, 4339, 4341, - 4343, 4345, 4347, 4349, 4351, 4353, 4355, 4357, 4359, 4361, 4363, - 4365, 4367, 4369, 4371, 4373, 4375, 4377, 4379, 4381, 4383, 4385, - 4387, 4389, 4391, 4393, 4395, 4397, 4399, 4401, 4403, 4405, 4407, - 4409, 4411, 4413, 4514, 4516, 6070, 6568, 6570, 4304, 3759, 3761, - 3763, 3765, 3777, 3779, 3781, 3783, 3785, 3787, 3789 }; - public static int boots[] = { 7596, 8029, 6619, 8017, 7159, 7991, 6666, - 6061, 6106, 88, 89, 626, 628, 630, 632, 634, 1061, 1837, 1846, - 2577, 2579, 2894, 2904, 2914, 2924, 2934, 3061, 3105, 3107, 3791, - 4097, 4107, 4117, 4119, 4121, 4123, 4125, 4127, 4129, 4131, 4310, - 5064, 5345, 5557, 6069, 6106, 6143, 6145, 6147, 6328, 6920, 6349, - 6357, 3393 }; - public static int gloves[] = { 7595, 6629, 8021, 8016, 7964, 2491, 1065, - 2487, 2489, 3060, 1495, 775, 777, 778, 6708, 1059, 1063, 1065, - 1580, 2487, 2489, 2491, 2902, 2912, 2922, 2932, 2942, 3060, 3799, - 4095, 4105, 4115, 4308, 5556, 6068, 6110, 6149, 6151, 6153, 6922, - 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, 6330, 3391, - 776 }; - public static int shields[] = { 7676, 7342, 7348, 7354, 7360, 7334, 7340, - 7347, 7352, 7358, 7356, 7350, 7344, 8087, 8058, 8059, 8060, 8061, - 8062, 8063, 6633, 7977, 7976, 7972, 7959, 6591, 7332, 7338, 7336, - 7360, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187, 1189, - 1191, 1193, 1195, 1197, 1199, 1201, 1540, 2589, 2597, 2603, 2611, - 2621, 2629, 2659, 2667, 2675, 2890, 3122, 3488, 3758, 3839, 3840, - 3841, 3842, 3843, 3844, 4072, 4156, 4224, 4225, 4226, 4227, 4228, - 4229, 4230, 4231, 4232, 4233, 4234, 4302, 4507, 4512, 6215, 6217, - 6219, 6221, 6223, 6225, 6227, 6229, 6231, 6233, 6235, 6237, 6239, - 6241, 6243, 6245, 6247, 6249, 6251, 6253, 6255, 6257, 6259, 6261, - 6263, 6265, 6267, 6269, 6271, 6273, 6275, 6277, 6279, 6524, 6889, - 7051, 7053 }; - public static int hats[] = { 2679, 1025, 2685, 4166, 2682, 2703, 2688, - 2691, 2691, 2733, 2736, 2718, 2730, 2697, 2715, 2727, 2724, 2709, - 2706, 2712, 2721, 2739, 2700, 2518, 2524, 2526, 7319, 7321, 7323, - 7325, 7327, 1167, 8077, 8076, 8074, 4168, 1169, 8034, 8035, 8036, - 8030, 6623, 8024, 8023, 8022, 8013, 1169, 7594, 7995, 7996, 7997, - 7998, 7999, 8000, 8001, 7992, 7990, 7975, 7973, 7971, 7967, 7963, - 6665, 6665, 7321, 6886, 6547, 6548, 2645, 2647, 2649, 4856, 4857, - 4858, 4859, 4880, 4881, 4882, 4883, 4904, 4905, 4906, 4907, 4928, - 4929, 4930, 4931, 4952, 4953, 4954, 4955, 4976, 4977, 4978, 4979, - 4732, 4753, 4611, 6188, 6182, 4511, 4056, 4071, 4724, 2639, 2641, - 2643, 2665, 6109, 5525, 5527, 5529, 5531, 5533, 5535, 5537, 5539, - 5541, 5543, 5545, 5547, 5549, 5551, 74, 579, 656, 658, 660, 662, - 664, 740, 1017, 1037, 1040, 1042, 1044, 1046, 1038, 1048, 1050, - 1053, 1055, 1057, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151, - 1153, 1155, 1157, 1159, 1161, 1163, 1165, 1506, 1949, 2422, 2581, - 2587, 2595, 2605, 2613, 2619, 2627, 2631, 2633, 2635, 2637, 2651, - 2657, 2673, 2900, 2910, 2920, 2930, 2940, 2978, 2979, 2980, 2981, - 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, - 2993, 2994, 2995, 3057, 3385, 3486, 3748, 3749, 3751, 3753, 3797, - 4041, 4042, 4071, 4089, 3755, 4099, 4109, 4164, 4302, 4506, 4511, - 4513, 4515, 4551, 4567, 4708, 4716, 4724, 4745, 4753, 4857, 4858, - 4859, 4880, 4881, 4882, 4883, 4904, 4905, 4906, 4907, 4952, 4953, - 4954, 4955, 4976, 4977, 4978, 4979, 5013, 5014, 5554, 5574, 6109, - 6128, 6131, 6137, 6182, 6188, 6335, 6337, 6339, 6345, 6355, 6365, - 6375, 6382, 6392, 6400, 6918, 6656, 2581, 7539, 7394, 7396, 7534, - 5574, 6885, 6858, 6860, 6862, 6856, 6326, 6128, 6137, 7400, 7323, - 7325, 7327, 7003, 4168, 7112, 7124, 7130, 7136 }; - public static int amulets[] = { 1654, 1656, 1658, 1660, 1662, 1664, 8081, - 8033, 7968, 6585, 86, 87, 295, 421, 552, 589, 1478, 1692, 1694, - 1696, 1698, 1700, 1702, 1704, 1706, 1708, 1710, 1712, 1725, 1727, - 1729, 1731, 4021, 4081, 4250, 4677, 6040, 6041, 6208, 1718, 1722, - 6859, 6863, 6857, 3853, 3855, 3857, 3859, 3861, 3863, 3865, 3867, - 1718, 4306, 1702 }; - public static int arrows[] = { 11212, 8052, 9211, 9010, 9209, 9208, 9207, - 9206, 9205, 9203, 9301, 8065, 7919, 7906, 7988, 7989, 78, 598, 877, - 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, - 891, 892, 893, 942, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, - 2540, 2541, 2866, 4160, 4172, 4173, 4174, 4175, 4740, 5616, 5617, - 5618, 5619, 5620, 5621, 5622, 5623, 5624, 5625, 5626, 5627, 6061, - 6062}; - public static int rings[] = { 8082, 773, 1635, 1637, 1639, 1641, 1643, - 1645, 2550, 2552, 2554, 2556, 2558, 2560, 2562, 2564, 2566, 2568, - 2570, 2572, 4202, 4657, 6465, 6737, 6731, 6735, 6583, 6733 }; - public static int body[] = { 7608, 2520, 430, 7362, 7364, 636, 638, 640, - 642, 644, 8064, 426, 430, 1005, 1757, 7592, 8031, 8027, 6617, 8019, - 8014, 8002, 7376, 544, 7372, 7370, 577, 7974, 7970, 7965, 7961, - 7960, 3793, 3775, 3773, 3771, 3769, 3767, 6139, 1135, 2499, 2501, - 1035, 540, 5553, 4757, 1833, 6388, 6384, 4111, 4101, 4091, 6186, - 6184, 6180, 3058, 4509, 4504, 4069, 4728, 4736, 4712, 6107, 2661, - 3140, 1101, 1103, 1105, 1107, 1109, 1111, 1113, 1115, 1117, 1119, - 1121, 1123, 1125, 1127, 1129, 1131, 1133, 2583, 2591, 2599, 2607, - 2615, 2623, 2653, 2669, 3481, 4712, 4720, 4728, 4749, 4892, 4893, - 4894, 4895, 4916, 4917, 4918, 4919, 4964, 4965, 4966, 4967, 6107, - 6133, 6322, 6322, 6129, 75, 6916, 6916, 4111, 6654, 6654, 75, 7399, 7374, 5575, 2503, 6341, 6351, 3387, 5030, 5032, 5034, 5030, - 5032, 5034,7390 , 7392, 546, 581 }; - public static int legs[] = { 7609, 2522, 7378, 7380, 7382, 7368, 7366, - 7388, 646, 648, 650, 652, 654, 428, 1097, 1095, 7593, 8032, 8028, - 6625, 8020, 8015, 7384, 7969, 7966, 7962, 6141, 538, 1033, 5555, - 4759, 6386, 6390, 2497, 2495, 2493, 1099, 4113, 4103, 4093, 6924, - 6187, 6185, 6181, 3059, 4510, 4505, 4070, 6108, 542, 548, 1011, - 1013, 1015, 1067, 1069, 1071, 1073, 1075, 1077, 1079, 1081, 1083, - 1085, 1087, 1089, 1091, 1093, 2585, 2593, 2601, 2609, 2617, 2625, - 2655, 2663, 2671, 3059, 3389, 3472, 3473, 3474, 3475, 3476, 3477, - 3478, 3479, 3480, 3483, 3485, 3795, 4087, 4585, 4712, 4714, 4722, - 4730, 4738, 4751, 4759, 4874, 4875, 4876, 4877, 4898, 4899, 4900, - 4901, 4922, 4923, 4924, 4925, 4946, 4947, 4948, 4949, 4970, 4971, - 4972, 4973, 4994, 4995, 4996, 4997, 5048, 5050, 5052, 5576, 6107, - 6130, 6187, 6390, 6386, 6390, 6394, 6396, 6402, 6404, 6135, 6809, 6916, 4091, - 4111, 6655, 6654, 7398, 7398, 7386, 6324, 6343, 6353, 6363, 6373, 3387, 5036, - 5038, 5040, 5042, 5044, 5046, 5050, 5052, 4300, 1835, 7116, 7126, 6752, - 7132, 7138 }; - public static int platebody[] = { 10338, 7608, 2520, 430, 636, 638, 640, - 642, 644, 426, 430, 8031, 8027, 6617, 8019, 8014, 8002, 544, 577, - 7974, 7970, 7965, 7961, 7960, 3793, 3773, 3775, 3771, 3769, 3767, - 6139, 1035, 540, 5553, 4757, 1833, 1835, 6388, 6384, 4111, 4101, - 4868, 4869, 4870, 4871, 4892, 4893, 4894, 4895, 4916, 4917, 4918, - 4919, 4940, 4941, 4942, 4943, 4964, 4965, 4966, 4967, 4988, 4989, - 4990, 0x2f9a0eb, 6186, 6184, 6180, 3058, 4509, 4504, 4069, 4728, - 4736, 4712, 6107, 2661, 3140, 1115, 1117, 1119, 1121, 1123, 1125, - 1127, 2583, 2591, 2599, 2607, 2615, 6322, 2623, 2653, 2669, 3481, - 4720, 4728, 4749, 2661, 6129, 6916, 4091, 6654, 6133, 75, 7399, 5575, 6341, 6351, 7390, 7392, 3387, 5024, 5030, 5032, 5034, 7392, 6786, 6788 }; + /** + * The id. + */ + private int id; - /* Fullbody is an item that covers your arms. */ - private static String[] fullbody = { - "top", "shirt", "platebody", "Wizard robe (g)", "Wizard robe (t)", - "Ahrims robetop", "Karils leathertop", "brassard", "Robe top", - "robetop", "platebody (t)", "platebody (g)", "chestplate", "torso", - "hauberk", "Dragon chainbody", "gown", "Shade robe", "Wizard robe", - "Druid's robe", "Black robe", "Fremennik robe", "Robe of elidinis", - "tunic", "blouse", "Wizard robe(g)", "Wizard robe(t)" - }; - /* Fullhat covers your head but not your beard. */ - private static String[] fullhat = { "med helm", "coif", "Dharok's helm", - "hood", "Initiate helm", "Coif", "Helm of neitiznot", - "Armadyl helmet", "Berserker helm", "Archer helm", "Farseer helm", - "Warrior helm", "Void"}; - /* Fullmask covers your entire head. */ - private static String[] fullmask = { "full helm(t)", "full helm(g)", "full helm", "mask", "Verac's helm", - "Guthan's helm", "Karil's coif", "mask", "Torag's helm", "Void", "helmet", - "sallet", "Facemask", "Bearhead"}; + /** + * The number of items. + */ + private int count; - public static boolean isFullBody(int itemId) { - String weapon = getItemName(itemId); - if (weapon == null) { - return false; - } - for (String element : fullbody) { - if (weapon.endsWith(element)) { - return true; - } - } - return false; + /** + * Creates a single item. + * + * @param id + * The id. + */ + public Item(int id) { + this(id, 1); } - public static boolean isFullHelm(int itemId) { - String weapon = getItemName(itemId); - if (weapon == null) { - return false; - } - for (String element : fullhat) { - if (weapon.endsWith(element)) { - return true; - } - } - return false; + public void setCount(int count) { + this.count = count; } - public static boolean isFullMask(int itemId) { - String weapon = getItemName(itemId); - if (weapon == null) { - return false; + /** + * Creates a stacked item. + * + * @param id + * The id. + * @param count + * The number of items. + * @throws IllegalArgumentException + * if count is negative. + */ + public Item(int id, int count) { + if (count < 0) { + throw new IllegalArgumentException("Count cannot be negative."); } - for (String element : fullmask) { - if (weapon.endsWith(element)) { - return true; - } - } - return false; + this.id = id; + this.count = count; } - public static String getItemName(int id) { - for (ItemList element : GameEngine.itemHandler.ItemList) { - if (element != null) { - if (element.itemId == id) { - return element.itemName; - } - } + /** + * Creates a stacked item. + * + * @param id + * The id. + * @param count + * The number of items. + * @param timer + * The timer assigned. + * @throws IllegalArgumentException + * if count is negative. + */ + public Item(int id, int count, int timer) { + if (count < 0) { + throw new IllegalArgumentException("Count cannot be negative."); } - return null; + this.id = id; + this.count = count; } - public static boolean[] itemStackable = new boolean[GameConstants.ITEM_LIMIT]; - public static boolean[] itemIsNote = new boolean[GameConstants.ITEM_LIMIT]; - public static int[] targetSlots = new int[GameConstants.ITEM_LIMIT]; - static { - int counter = 0; - int c; - - try { - FileInputStream dataIn = new FileInputStream(new File("./data/data/stackable.dat")); - while ((c = dataIn.read()) != -1) { - if (c == 0) { - itemStackable[counter] = false; - itemStackable[291] = true; - } else { - itemStackable[counter] = true; - } - counter++; - } - dataIn.close(); - } catch (IOException e) { - System.out.println("Critical error while loading stackabledata! Trace:"); - e.printStackTrace(); - } - - counter = 0; - try { - FileInputStream dataIn = new FileInputStream(new File("./data/data/notes.dat")); - while ((c = dataIn.read()) != -1) { - itemIsNote[counter] = c == 0; - counter++; - } - dataIn.close(); - } catch (IOException e) { - System.out.println("Critical error while loading notedata! Trace:"); - e.printStackTrace(); - } - - counter = 0; - try { - FileInputStream dataIn = new FileInputStream(new File("./data/data/equipment.dat")); - while ((c = dataIn.read()) != -1) { - int slot; - // rebind item equip slot here - switch (counter) { - // Legs - case 6181: - case 428: - case 538: - case 6343: - case 6353: - case 6363: - case 6396: - case 6373: - case 6404: - case 5044: - case 5046: - case 5050: - case 5052: - case 5040: - case 5038: - case 6752: - case 5048: - case 5036: - case 5042: - case 4300: - case 1835: - case 7116: - case 7126: - case 7132: - case 7138: - case 548: - case 6185: - slot = GameConstants.LEGS; - break; - // Hats - case 4166: - case 1167: - case 5525: - case 4168: - case 4502: - case 1037: - case 1025: - case 7112: - case 7124: - case 7130: - case 7136: - case 4611: - case 5527: - case 5529: - case 5531: - case 5533: - case 5535: - case 5537: - case 5539: - case 5541: - case 5543: - case 5545: - case 5547: - slot = GameConstants.HAT; - break; - // Cape - case 4304: - case 3759: - case 3761: - case 3763: - case 3765: - case 3777: - case 3779: - case 3781: - case 3783: - case 3785: - case 3787: - case 3789: - case 4514: - case 4516: - slot = GameConstants.CAPE; - break; - // Shield - case 7051: - case 7053: - slot = GameConstants.SHIELD; - break; - // Chest - case 577: - case 426: - case 540: - case 430: - case 6786: - case 581: - case 5024: - case 5030: - case 1757: - case 5034: - case 5032: - case 3793: - case 1005: - case 546: - case 6402: - case 6788: - case 6184: - case 7390: - case 7392: - case 6186: - slot = GameConstants.CHEST; - break; - // Amulet - case 3853: - case 3855: - case 3857: - case 3859: - case 3861: - case 3863: - case 1718: - case 3865: - case 4306: - case 3867: - case 1702: - slot = GameConstants.AMULET; - break; - // Hands - case 776: - slot = GameConstants.HANDS; - break; - default: - slot = c; - } - targetSlots[counter] = slot; - counter++; - } - dataIn.close(); - } catch (IOException e) { - System.out.println("Critical error while loading equipment data! Trace:"); - e.printStackTrace(); - } + /** + * Gets the item id. + * + * @return The item id. + */ + public int getId() { + return id; } -} + /** + * Gets the count. + * + * @return The count. + */ + public int getCount() { + return count; + } + + @Override + public String toString() { + return Item.class.getName() + " [id=" + id + ", count=" + count + "]"; + } + + public boolean equals(Item item) { + return item.getId() == id && count == item.getCount(); + } + + public ItemList getDefinition() { + return GameEngine.itemHandler.ItemList[id]; + } +} \ No newline at end of file diff --git a/2006Redone Server/src/main/java/com/rebotted/game/items/ItemAssistant.java b/2006Redone Server/src/main/java/com/rebotted/game/items/ItemAssistant.java index 0091c8a8..169438bb 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/items/ItemAssistant.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/items/ItemAssistant.java @@ -241,12 +241,12 @@ public class ItemAssistant { public int getTotalCount(int itemID) { int count = 0; for (int j = 0; j < c.playerItems.length; j++) { - if (Item.itemIsNote[itemID + 1]) { + if (ItemData.itemIsNote[itemID + 1]) { if (itemID + 2 == c.playerItems[j]) { count += c.playerItemsN[j]; } } - if (!Item.itemIsNote[itemID + 1]) { + if (!ItemData.itemIsNote[itemID + 1]) { if (itemID + 1 == c.playerItems[j]) { count += c.playerItemsN[j]; } @@ -466,10 +466,10 @@ public class ItemAssistant { return false; } if ((freeSlots() >= 1 || playerHasItem(item, 1)) - && Item.itemStackable[item] || freeSlots() > 0 - && !Item.itemStackable[item]) { + && ItemData.itemStackable[item] || freeSlots() > 0 + && !ItemData.itemStackable[item]) { for (int i = 0; i < c.playerItems.length; i++) { - if (c.playerItems[i] == item + 1 && Item.itemStackable[item] + if (c.playerItems[i] == item + 1 && ItemData.itemStackable[item] && c.playerItems[i] > 0) { c.playerItems[i] = item + 1; if (c.playerItemsN[i] + amount < GameConstants.MAXITEM_AMOUNT @@ -1298,7 +1298,7 @@ public class ItemAssistant { boolean canWearItem = true; if (c.playerItems[slot] == wearID + 1) { getRequirements(getItemName(wearID).toLowerCase(), wearID); - targetSlot = Item.targetSlots[wearID]; + targetSlot = ItemData.targetSlots[wearID]; if (c.duelRule[11] && targetSlot == 0) { c.getPacketSender().sendMessage("Wearing hats has been disabled in this duel!"); @@ -1447,7 +1447,7 @@ public class ItemAssistant { int toEquipN = c.playerItemsN[slot]; int toRemove = c.playerEquipment[targetSlot]; int toRemoveN = c.playerEquipmentN[targetSlot]; - if (toEquip == toRemove + 1 && Item.itemStackable[toRemove]) { + if (toEquip == toRemove + 1 && ItemData.itemStackable[toRemove]) { deleteItem(toRemove, getItemSlot(toRemove), toEquipN); c.playerEquipmentN[targetSlot] += toEquipN; } else if (targetSlot != GameConstants.SHIELD && targetSlot != GameConstants.WEAPON) { @@ -1781,11 +1781,11 @@ public class ItemAssistant { if (c.playerItemsN[fromSlot] <= 0) { return false; } - if (!Item.itemIsNote[c.playerItems[fromSlot] - 1]) { + if (!ItemData.itemIsNote[c.playerItems[fromSlot] - 1]) { if (c.playerItems[fromSlot] <= 0) { return false; } - if (Item.itemStackable[c.playerItems[fromSlot] - 1] || c.playerItemsN[fromSlot] > 1) { + if (ItemData.itemStackable[c.playerItems[fromSlot] - 1] || c.playerItemsN[fromSlot] > 1) { int toBankSlot = 0; boolean alreadyInBank = false; for (int i = 0; i < GameConstants.BANK_SIZE; i++) { @@ -1908,11 +1908,11 @@ public class ItemAssistant { return false; } } - } else if (Item.itemIsNote[c.playerItems[fromSlot] - 1] && !Item.itemIsNote[c.playerItems[fromSlot] - 2]) { + } else if (ItemData.itemIsNote[c.playerItems[fromSlot] - 1] && !ItemData.itemIsNote[c.playerItems[fromSlot] - 2]) { if (c.playerItems[fromSlot] <= 0) { return false; } - if (Item.itemStackable[c.playerItems[fromSlot] - 1] || c.playerItemsN[fromSlot] > 1) { + if (ItemData.itemStackable[c.playerItems[fromSlot] - 1] || c.playerItemsN[fromSlot] > 1) { int toBankSlot = 0; boolean alreadyInBank = false; for (int i = 0; i < GameConstants.BANK_SIZE; i++) { @@ -2084,7 +2084,7 @@ public class ItemAssistant { if (!cantWithdrawCuzMaxStack) { if (!c.takeAsNote) { - if (Item.itemStackable[c.bankItems[fromSlot] - 1]) { + if (ItemData.itemStackable[c.bankItems[fromSlot] - 1]) { if (c.bankItemsN[fromSlot] > amount) { if (addItem(c.bankItems[fromSlot] - 1, amount)) { c.bankItemsN[fromSlot] -= amount; @@ -2116,7 +2116,7 @@ public class ItemAssistant { resetBank(); resetItems(5064); } - } else if (c.takeAsNote && Item.itemIsNote[c.bankItems[fromSlot]]) { + } else if (c.takeAsNote && ItemData.itemIsNote[c.bankItems[fromSlot]]) { if (c.bankItemsN[fromSlot] > amount) { if (addItem(c.bankItems[fromSlot], amount)) { c.bankItemsN[fromSlot] -= amount; @@ -2133,7 +2133,7 @@ public class ItemAssistant { } } else { c.getPacketSender().sendMessage("This item can't be withdrawn as a note."); - if (Item.itemStackable[c.bankItems[fromSlot] - 1]) { + if (ItemData.itemStackable[c.bankItems[fromSlot] - 1]) { if (c.bankItemsN[fromSlot] > amount) { if (addItem(c.bankItems[fromSlot] - 1, amount)) { c.bankItemsN[fromSlot] -= amount; @@ -2186,7 +2186,7 @@ public class ItemAssistant { } public boolean isStackable(int itemID) { - return Item.itemStackable[itemID]; + return ItemData.itemStackable[itemID]; } /** diff --git a/2006Redone Server/src/main/java/com/rebotted/game/items/ItemData.java b/2006Redone Server/src/main/java/com/rebotted/game/items/ItemData.java new file mode 100644 index 00000000..418c6653 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/items/ItemData.java @@ -0,0 +1,376 @@ +package com.rebotted.game.items; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import com.rebotted.GameConstants; +import com.rebotted.GameEngine; + +public class ItemData { + + public static int capes[] = { 2731, 2677, 2683, 2680, 2701, 2686, 2689, + 2692, 2737, 2734, 2716, 2728, 2695, 2713, 2725, 2722, 2707, 2704, + 2710, 2719, 2737, 2698, 14590, 2701, 8102, 8075, 8044, 8045, 8042, + 8043, 8037, 8038, 8025, 8026, 8018, 7858, 7994, 7983, 7984, 7985, + 7986, 7987, 7982, 7978, 3781, 3783, 3785, 3787, 3789, 3777, 3779, + 3759, 3761, 3763, 3765, 6111, 6570, 6568, 1007, 1019, 1021, 1023, + 1027, 1029, 1031, 1052, 2412, 2413, 2414, 4304, 4315, 4317, 4319, + 4321, 4323, 4325, 4327, 4329, 4331, 4333, 4335, 4337, 4339, 4341, + 4343, 4345, 4347, 4349, 4351, 4353, 4355, 4357, 4359, 4361, 4363, + 4365, 4367, 4369, 4371, 4373, 4375, 4377, 4379, 4381, 4383, 4385, + 4387, 4389, 4391, 4393, 4395, 4397, 4399, 4401, 4403, 4405, 4407, + 4409, 4411, 4413, 4514, 4516, 6070, 6568, 6570, 4304, 3759, 3761, + 3763, 3765, 3777, 3779, 3781, 3783, 3785, 3787, 3789 }; + public static int boots[] = { 7596, 8029, 6619, 8017, 7159, 7991, 6666, + 6061, 6106, 88, 89, 626, 628, 630, 632, 634, 1061, 1837, 1846, + 2577, 2579, 2894, 2904, 2914, 2924, 2934, 3061, 3105, 3107, 3791, + 4097, 4107, 4117, 4119, 4121, 4123, 4125, 4127, 4129, 4131, 4310, + 5064, 5345, 5557, 6069, 6106, 6143, 6145, 6147, 6328, 6920, 6349, + 6357, 3393 }; + public static int gloves[] = { 7595, 6629, 8021, 8016, 7964, 2491, 1065, + 2487, 2489, 3060, 1495, 775, 777, 778, 6708, 1059, 1063, 1065, + 1580, 2487, 2489, 2491, 2902, 2912, 2922, 2932, 2942, 3060, 3799, + 4095, 4105, 4115, 4308, 5556, 6068, 6110, 6149, 6151, 6153, 6922, + 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, 6330, 3391, + 776 }; + public static int shields[] = { 7676, 7342, 7348, 7354, 7360, 7334, 7340, + 7347, 7352, 7358, 7356, 7350, 7344, 8087, 8058, 8059, 8060, 8061, + 8062, 8063, 6633, 7977, 7976, 7972, 7959, 6591, 7332, 7338, 7336, + 7360, 1171, 1173, 1175, 1177, 1179, 1181, 1183, 1185, 1187, 1189, + 1191, 1193, 1195, 1197, 1199, 1201, 1540, 2589, 2597, 2603, 2611, + 2621, 2629, 2659, 2667, 2675, 2890, 3122, 3488, 3758, 3839, 3840, + 3841, 3842, 3843, 3844, 4072, 4156, 4224, 4225, 4226, 4227, 4228, + 4229, 4230, 4231, 4232, 4233, 4234, 4302, 4507, 4512, 6215, 6217, + 6219, 6221, 6223, 6225, 6227, 6229, 6231, 6233, 6235, 6237, 6239, + 6241, 6243, 6245, 6247, 6249, 6251, 6253, 6255, 6257, 6259, 6261, + 6263, 6265, 6267, 6269, 6271, 6273, 6275, 6277, 6279, 6524, 6889, + 7051, 7053 }; + public static int hats[] = { 2679, 1025, 2685, 4166, 2682, 2703, 2688, + 2691, 2691, 2733, 2736, 2718, 2730, 2697, 2715, 2727, 2724, 2709, + 2706, 2712, 2721, 2739, 2700, 2518, 2524, 2526, 7319, 7321, 7323, + 7325, 7327, 1167, 8077, 8076, 8074, 4168, 1169, 8034, 8035, 8036, + 8030, 6623, 8024, 8023, 8022, 8013, 1169, 7594, 7995, 7996, 7997, + 7998, 7999, 8000, 8001, 7992, 7990, 7975, 7973, 7971, 7967, 7963, + 6665, 6665, 7321, 6886, 6547, 6548, 2645, 2647, 2649, 4856, 4857, + 4858, 4859, 4880, 4881, 4882, 4883, 4904, 4905, 4906, 4907, 4928, + 4929, 4930, 4931, 4952, 4953, 4954, 4955, 4976, 4977, 4978, 4979, + 4732, 4753, 4611, 6188, 6182, 4511, 4056, 4071, 4724, 2639, 2641, + 2643, 2665, 6109, 5525, 5527, 5529, 5531, 5533, 5535, 5537, 5539, + 5541, 5543, 5545, 5547, 5549, 5551, 74, 579, 656, 658, 660, 662, + 664, 740, 1017, 1037, 1040, 1042, 1044, 1046, 1038, 1048, 1050, + 1053, 1055, 1057, 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151, + 1153, 1155, 1157, 1159, 1161, 1163, 1165, 1506, 1949, 2422, 2581, + 2587, 2595, 2605, 2613, 2619, 2627, 2631, 2633, 2635, 2637, 2651, + 2657, 2673, 2900, 2910, 2920, 2930, 2940, 2978, 2979, 2980, 2981, + 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, + 2993, 2994, 2995, 3057, 3385, 3486, 3748, 3749, 3751, 3753, 3797, + 4041, 4042, 4071, 4089, 3755, 4099, 4109, 4164, 4302, 4506, 4511, + 4513, 4515, 4551, 4567, 4708, 4716, 4724, 4745, 4753, 4857, 4858, + 4859, 4880, 4881, 4882, 4883, 4904, 4905, 4906, 4907, 4952, 4953, + 4954, 4955, 4976, 4977, 4978, 4979, 5013, 5014, 5554, 5574, 6109, + 6128, 6131, 6137, 6182, 6188, 6335, 6337, 6339, 6345, 6355, 6365, + 6375, 6382, 6392, 6400, 6918, 6656, 2581, 7539, 7394, 7396, 7534, + 5574, 6885, 6858, 6860, 6862, 6856, 6326, 6128, 6137, 7400, 7323, + 7325, 7327, 7003, 4168, 7112, 7124, 7130, 7136 }; + public static int amulets[] = { 1654, 1656, 1658, 1660, 1662, 1664, 8081, + 8033, 7968, 6585, 86, 87, 295, 421, 552, 589, 1478, 1692, 1694, + 1696, 1698, 1700, 1702, 1704, 1706, 1708, 1710, 1712, 1725, 1727, + 1729, 1731, 4021, 4081, 4250, 4677, 6040, 6041, 6208, 1718, 1722, + 6859, 6863, 6857, 3853, 3855, 3857, 3859, 3861, 3863, 3865, 3867, + 1718, 4306, 1702 }; + public static int arrows[] = { 11212, 8052, 9211, 9010, 9209, 9208, 9207, + 9206, 9205, 9203, 9301, 8065, 7919, 7906, 7988, 7989, 78, 598, 877, + 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, + 891, 892, 893, 942, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, + 2540, 2541, 2866, 4160, 4172, 4173, 4174, 4175, 4740, 5616, 5617, + 5618, 5619, 5620, 5621, 5622, 5623, 5624, 5625, 5626, 5627, 6061, + 6062}; + public static int rings[] = { 8082, 773, 1635, 1637, 1639, 1641, 1643, + 1645, 2550, 2552, 2554, 2556, 2558, 2560, 2562, 2564, 2566, 2568, + 2570, 2572, 4202, 4657, 6465, 6737, 6731, 6735, 6583, 6733 }; + public static int body[] = { 7608, 2520, 430, 7362, 7364, 636, 638, 640, + 642, 644, 8064, 426, 430, 1005, 1757, 7592, 8031, 8027, 6617, 8019, + 8014, 8002, 7376, 544, 7372, 7370, 577, 7974, 7970, 7965, 7961, + 7960, 3793, 3775, 3773, 3771, 3769, 3767, 6139, 1135, 2499, 2501, + 1035, 540, 5553, 4757, 1833, 6388, 6384, 4111, 4101, 4091, 6186, + 6184, 6180, 3058, 4509, 4504, 4069, 4728, 4736, 4712, 6107, 2661, + 3140, 1101, 1103, 1105, 1107, 1109, 1111, 1113, 1115, 1117, 1119, + 1121, 1123, 1125, 1127, 1129, 1131, 1133, 2583, 2591, 2599, 2607, + 2615, 2623, 2653, 2669, 3481, 4712, 4720, 4728, 4749, 4892, 4893, + 4894, 4895, 4916, 4917, 4918, 4919, 4964, 4965, 4966, 4967, 6107, + 6133, 6322, 6322, 6129, 75, 6916, 6916, 4111, 6654, 6654, 75, 7399, 7374, 5575, 2503, 6341, 6351, 3387, 5030, 5032, 5034, 5030, + 5032, 5034,7390 , 7392, 546, 581 }; + public static int legs[] = { 7609, 2522, 7378, 7380, 7382, 7368, 7366, + 7388, 646, 648, 650, 652, 654, 428, 1097, 1095, 7593, 8032, 8028, + 6625, 8020, 8015, 7384, 7969, 7966, 7962, 6141, 538, 1033, 5555, + 4759, 6386, 6390, 2497, 2495, 2493, 1099, 4113, 4103, 4093, 6924, + 6187, 6185, 6181, 3059, 4510, 4505, 4070, 6108, 542, 548, 1011, + 1013, 1015, 1067, 1069, 1071, 1073, 1075, 1077, 1079, 1081, 1083, + 1085, 1087, 1089, 1091, 1093, 2585, 2593, 2601, 2609, 2617, 2625, + 2655, 2663, 2671, 3059, 3389, 3472, 3473, 3474, 3475, 3476, 3477, + 3478, 3479, 3480, 3483, 3485, 3795, 4087, 4585, 4712, 4714, 4722, + 4730, 4738, 4751, 4759, 4874, 4875, 4876, 4877, 4898, 4899, 4900, + 4901, 4922, 4923, 4924, 4925, 4946, 4947, 4948, 4949, 4970, 4971, + 4972, 4973, 4994, 4995, 4996, 4997, 5048, 5050, 5052, 5576, 6107, + 6130, 6187, 6390, 6386, 6390, 6394, 6396, 6402, 6404, 6135, 6809, 6916, 4091, + 4111, 6655, 6654, 7398, 7398, 7386, 6324, 6343, 6353, 6363, 6373, 3387, 5036, + 5038, 5040, 5042, 5044, 5046, 5050, 5052, 4300, 1835, 7116, 7126, 6752, + 7132, 7138 }; + public static int platebody[] = { 10338, 7608, 2520, 430, 636, 638, 640, + 642, 644, 426, 430, 8031, 8027, 6617, 8019, 8014, 8002, 544, 577, + 7974, 7970, 7965, 7961, 7960, 3793, 3773, 3775, 3771, 3769, 3767, + 6139, 1035, 540, 5553, 4757, 1833, 1835, 6388, 6384, 4111, 4101, + 4868, 4869, 4870, 4871, 4892, 4893, 4894, 4895, 4916, 4917, 4918, + 4919, 4940, 4941, 4942, 4943, 4964, 4965, 4966, 4967, 4988, 4989, + 4990, 0x2f9a0eb, 6186, 6184, 6180, 3058, 4509, 4504, 4069, 4728, + 4736, 4712, 6107, 2661, 3140, 1115, 1117, 1119, 1121, 1123, 1125, + 1127, 2583, 2591, 2599, 2607, 2615, 6322, 2623, 2653, 2669, 3481, + 4720, 4728, 4749, 2661, 6129, 6916, 4091, 6654, 6133, 75, 7399, 5575, 6341, 6351, 7390, 7392, 3387, 5024, 5030, 5032, 5034, 7392, 6786, 6788 }; + + /* Fullbody is an item that covers your arms. */ + private static String[] fullbody = { + "top", "shirt", "platebody", "Wizard robe (g)", "Wizard robe (t)", + "Ahrims robetop", "Karils leathertop", "brassard", "Robe top", + "robetop", "platebody (t)", "platebody (g)", "chestplate", "torso", + "hauberk", "Dragon chainbody", "gown", "Shade robe", "Wizard robe", + "Druid's robe", "Black robe", "Fremennik robe", "Robe of elidinis", + "tunic", "blouse", "Wizard robe(g)", "Wizard robe(t)" + }; + /* Fullhat covers your head but not your beard. */ + private static String[] fullhat = { "med helm", "coif", "Dharok's helm", + "hood", "Initiate helm", "Coif", "Helm of neitiznot", + "Armadyl helmet", "Berserker helm", "Archer helm", "Farseer helm", + "Warrior helm", "Void"}; + /* Fullmask covers your entire head. */ + private static String[] fullmask = { "full helm(t)", "full helm(g)", "full helm", "mask", "Verac's helm", + "Guthan's helm", "Karil's coif", "mask", "Torag's helm", "Void", "helmet", + "sallet", "Facemask", "Bearhead"}; + + public static boolean isFullBody(int itemId) { + String weapon = getItemName(itemId); + if (weapon == null) { + return false; + } + for (String element : fullbody) { + if (weapon.endsWith(element)) { + return true; + } + } + return false; + } + + public static boolean isFullHelm(int itemId) { + String weapon = getItemName(itemId); + if (weapon == null) { + return false; + } + for (String element : fullhat) { + if (weapon.endsWith(element)) { + return true; + } + } + return false; + } + + public static boolean isFullMask(int itemId) { + String weapon = getItemName(itemId); + if (weapon == null) { + return false; + } + for (String element : fullmask) { + if (weapon.endsWith(element)) { + return true; + } + } + return false; + } + + public static String getItemName(int id) { + for (ItemList element : GameEngine.itemHandler.ItemList) { + if (element != null) { + if (element.itemId == id) { + return element.itemName; + } + } + } + return null; + } + + public static boolean[] itemStackable = new boolean[GameConstants.ITEM_LIMIT]; + public static boolean[] itemIsNote = new boolean[GameConstants.ITEM_LIMIT]; + public static int[] targetSlots = new int[GameConstants.ITEM_LIMIT]; + static { + int counter = 0; + int c; + + try { + FileInputStream dataIn = new FileInputStream(new File("./data/data/stackable.dat")); + while ((c = dataIn.read()) != -1) { + if (c == 0) { + itemStackable[counter] = false; + itemStackable[291] = true; + } else { + itemStackable[counter] = true; + } + counter++; + } + dataIn.close(); + } catch (IOException e) { + System.out.println("Critical error while loading stackabledata! Trace:"); + e.printStackTrace(); + } + + counter = 0; + try { + FileInputStream dataIn = new FileInputStream(new File("./data/data/notes.dat")); + while ((c = dataIn.read()) != -1) { + itemIsNote[counter] = c == 0; + counter++; + } + dataIn.close(); + } catch (IOException e) { + System.out.println("Critical error while loading notedata! Trace:"); + e.printStackTrace(); + } + + counter = 0; + try { + FileInputStream dataIn = new FileInputStream(new File("./data/data/equipment.dat")); + while ((c = dataIn.read()) != -1) { + int slot; + // rebind item equip slot here + switch (counter) { + // Legs + case 6181: + case 428: + case 538: + case 6343: + case 6353: + case 6363: + case 6396: + case 6373: + case 6404: + case 5044: + case 5046: + case 5050: + case 5052: + case 5040: + case 5038: + case 6752: + case 5048: + case 5036: + case 5042: + case 4300: + case 1835: + case 7116: + case 7126: + case 7132: + case 7138: + case 548: + case 6185: + slot = GameConstants.LEGS; + break; + // Hats + case 4166: + case 1167: + case 5525: + case 4168: + case 4502: + case 1037: + case 1025: + case 7112: + case 7124: + case 7130: + case 7136: + case 4611: + case 5527: + case 5529: + case 5531: + case 5533: + case 5535: + case 5537: + case 5539: + case 5541: + case 5543: + case 5545: + case 5547: + slot = GameConstants.HAT; + break; + // Cape + case 4304: + case 3759: + case 3761: + case 3763: + case 3765: + case 3777: + case 3779: + case 3781: + case 3783: + case 3785: + case 3787: + case 3789: + case 4514: + case 4516: + slot = GameConstants.CAPE; + break; + // Shield + case 7051: + case 7053: + slot = GameConstants.SHIELD; + break; + // Chest + case 577: + case 426: + case 540: + case 430: + case 6786: + case 581: + case 5024: + case 5030: + case 1757: + case 5034: + case 5032: + case 3793: + case 1005: + case 546: + case 6402: + case 6788: + case 6184: + case 7390: + case 7392: + case 6186: + slot = GameConstants.CHEST; + break; + // Amulet + case 3853: + case 3855: + case 3857: + case 3859: + case 3861: + case 3863: + case 1718: + case 3865: + case 4306: + case 3867: + case 1702: + slot = GameConstants.AMULET; + break; + // Hands + case 776: + slot = GameConstants.HANDS; + break; + default: + slot = c; + } + targetSlots[counter] = slot; + counter++; + } + dataIn.close(); + } catch (IOException e) { + System.out.println("Critical error while loading equipment data! Trace:"); + e.printStackTrace(); + } + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/game/items/UseItem.java b/2006Redone Server/src/main/java/com/rebotted/game/items/UseItem.java index a1d83dcd..0c529053 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/items/UseItem.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/items/UseItem.java @@ -1,10 +1,12 @@ package com.rebotted.game.items; import com.rebotted.game.content.skills.cooking.Cooking; +import com.rebotted.game.content.skills.crafting.BattleStaffs; import com.rebotted.game.content.skills.crafting.GemCutting; import com.rebotted.game.content.skills.crafting.JewelryMaking; import com.rebotted.game.content.skills.crafting.LeatherMaking; import com.rebotted.game.content.skills.crafting.SoftClay; +import com.rebotted.game.content.skills.farming.Farming; import com.rebotted.game.content.skills.firemaking.Firemaking; import com.rebotted.game.content.skills.fletching.ArrowMaking; import com.rebotted.game.content.skills.fletching.LogCutting; @@ -47,6 +49,9 @@ public class UseItem { if (itemId == Ectofuntus.BUCKET) { Ectofuntus.fillBucketWithSlime(c, objectID); } + if (Farming.prepareCrop(c, itemId, objectID, objectX, objectY)) { + return; + } for (final EctofuntusData ectofuntus : EctofuntusData.values()) { if (itemId == ectofuntus.getBoneId()) { Ectofuntus.boneOnLoader(c, objectID, itemId); @@ -124,6 +129,7 @@ public class UseItem { && ItemAssistant.getItemName(useWith).contains("(")) { player.getPotMixing().mixPotion2(itemUsed, useWith); } + BattleStaffs.makeBattleStaff(player, itemUsed, useWith); GrindingAction.init(player, itemUsed, useWith); CapeDye.dyeItem(player, itemUsed, useWith); GodPages.itemOnItemHandle(player, useWith, itemUsed); diff --git a/2006Redone Server/src/main/java/com/rebotted/game/items/impl/CapeDye.java b/2006Redone Server/src/main/java/com/rebotted/game/items/impl/CapeDye.java index 1e0af200..7638615b 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/items/impl/CapeDye.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/items/impl/CapeDye.java @@ -1,6 +1,6 @@ package com.rebotted.game.items.impl; -import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemData; import com.rebotted.game.items.ItemAssistant; import com.rebotted.game.players.Player; @@ -47,10 +47,10 @@ public enum CapeDye { }; public static boolean blockDye(Player player, CapeDye dye, int itemUsed, int useWith) { - if (itemUsed == dye.getItemUsed() && ItemAssistant.getItemName(useWith).equalsIgnoreCase("Cape") && Item.itemIsNote[useWith]) { + if (itemUsed == dye.getItemUsed() && ItemAssistant.getItemName(useWith).equalsIgnoreCase("Cape") && ItemData.itemIsNote[useWith]) { player.getPacketSender().sendMessage("You can't dye a noted cape."); return true; - } else if (itemUsed == dye.getItemUsed() && ItemAssistant.getItemName(useWith).equalsIgnoreCase("Cape") && useWith == dye.getReward() && !Item.itemIsNote[useWith]) { + } else if (itemUsed == dye.getItemUsed() && ItemAssistant.getItemName(useWith).equalsIgnoreCase("Cape") && useWith == dye.getReward() && !ItemData.itemIsNote[useWith]) { player.getPacketSender().sendMessage("That cape is already that color."); return true; } else if (itemUsed == dye.getItemUsed() && !ItemAssistant.getItemName(useWith).equalsIgnoreCase("Cape")) { @@ -64,7 +64,7 @@ public enum CapeDye { if (blockDye(player, cape, itemUsed, useWith)) { return; } - if (itemUsed == cape.getItemUsed() && ItemAssistant.getItemName(useWith).equalsIgnoreCase("Cape") && !Item.itemIsNote[useWith] && useWith != cape.getReward()) { + if (itemUsed == cape.getItemUsed() && ItemAssistant.getItemName(useWith).equalsIgnoreCase("Cape") && !ItemData.itemIsNote[useWith] && useWith != cape.getReward()) { player.getItemAssistant().deleteItem(itemUsed, 1); player.getItemAssistant().deleteItem(useWith, 1); player.getItemAssistant().addItem(cape.getReward(), 1); diff --git a/2006Redone Server/src/main/java/com/rebotted/game/items/impl/GodBooks.java b/2006Redone Server/src/main/java/com/rebotted/game/items/impl/GodBooks.java new file mode 100644 index 00000000..7c4d5dea --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/game/items/impl/GodBooks.java @@ -0,0 +1,127 @@ +package com.rebotted.game.items.impl; + +import java.util.HashMap; +import java.util.Map; + +import com.rebotted.event.CycleEvent; +import com.rebotted.event.CycleEventContainer; +import com.rebotted.event.CycleEventHandler; +import com.rebotted.game.players.Player; + +/** + * Handles the preaching of god books + * @author Final Project + * + */ +public enum GodBooks { + + HOLY_BOOK(3840, new String[][] { + {"9178", "In the name of Saradomin,", "Protector of us all,", "I now join you in the eyes of Saradomin.", null}, + {"9179", "Thy cause was false, thy skills did lack.", "See you in lumbridge when you get back", null}, + {"9180", "Go in peace in the name of Saradomin,", "May his glory shine upon you like the sun.", null}, + {"9181", "Walk proud, and show mercy,", "For you carry my name in your heart,", "This is Saradomin's wisdom.", null} + }), + BOOK_OF_BALANCE(3844, new String[][] { + {"9178", "Light and dark, day and night,", "Balance arises from contrast.", "I unify thee in the name of Guthix.", null}, + {"9179", "Thy death was not in vain,", "For it brought some balance to the world.", "May Guthix bring you rest.", null}, + {"9180", "May you walk the path and never fall,", "For guthix walks beside thee on thy journey.", "May Guthix bring you peace.", null}, + {"9181", "A Journey of a single step,", "May take thee over a thousand miles.", "May Guthix bring you balance.", null} + }), + UNHOLY_BOOK(3842, new String[][] { + {"9178", "Two great warriors, joined by hand,", "to spread destruction across the land.", "In Zamorak's name, now two are one.", null}, + {"9179", "The weak deserve to die,", "So that the strong may flourish.", "This is the creed of Zamorak.", null}, + {"9180", "May your bloodthirst be never sated,", "and may all your battles be glorious.", "Zamorak bring you strength", null}, + {"9181", "There is no opinion that cannot be proven true,", "by crushing those who choose to disagree with it.", "Zamorak give me strength!", null} + }); + + private int itemId; + + private String[][] preachData; + + private GodBooks(int itemId, String[][] preachData) { + this.itemId = itemId; + this.preachData = preachData; + } + + private static Map godBooks = new HashMap(); + + static { + for (final GodBooks type : values()) { + godBooks.put(type.itemId, type); + } + } + + /** + * Sends the options dialogue with preach options + * @param player + * the player to send the options to + * @param itemId + * the item the player's interacting with + */ + public static void sendPreachOptions(Player player, int itemId) { + player.preaching = true; + switch (itemId) { + case 3840: + player.getDialogueHandler().sendOption("Partnership", "Blessing","Last Rights", "Preach"); + player.dialogueAction = 3840; + break; + case 3842: + case 3844: + player.getDialogueHandler().sendOption("Wedding Ceremony", "Blessing", "Last Rights", "Preach"); + player.dialogueAction = 3842; + break; + } + } + + /** + * Handles the preaching action + * @param player + * the player preaching + * @param itemId + * the item the player's interacting with + * @param actionButtonId + * the button id the player's interacting with + */ + public static void handlePreach(Player player, int itemId, int actionButtonId) { + player.getPacketSender().closeAllWindows(); + GodBooks books = godBooks.get(itemId); + if (player.specAmount < 2.5) { + player.getPacketSender().sendMessage("You need at least 25% of special attack to preach!"); + return; + } + if (itemId == books.itemId) { + player.specAmount -= 2.5; + player.getItemAssistant().updateSpecialBar(); + CycleEventHandler.getSingleton().addEvent(player, new CycleEvent() { + + private int currentQuote = 1; + + @Override + public void execute(CycleEventContainer container) { + for (int preaches = 0; preaches < books.preachData.length; preaches++) { + if (actionButtonId == Integer.parseInt(books.preachData[preaches][0])) { + if (books.preachData[preaches][currentQuote] == null) { + container.stop(); + return; + } + if (books.preachData[preaches][currentQuote] != null) { + player.startAnimation(1670); + player.forcedChat(books.preachData[preaches][currentQuote]); + currentQuote++; + } + break; + } + } + } + + @Override + public void stop() { + currentQuote = 1; + player.preaching = false; + } + + }, 1); + } + } + +} \ No newline at end of file diff --git a/2006Redone Server/src/main/java/com/rebotted/game/npcs/NpcActions.java b/2006Redone Server/src/main/java/com/rebotted/game/npcs/NpcActions.java index 68b14123..caa0dbfb 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/npcs/NpcActions.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/npcs/NpcActions.java @@ -38,6 +38,28 @@ public class NpcActions { } } switch (npcType) { + case 2324 : + case 2323 : + case 2326 : + case 2325 : + case 2337 : + case 2336 : + case 2335 : + case 2338 : + case 2334 : + case 2332 : + case 2333 : + case 2327 : + case 2343 : + case 2331 : + case 2344 : + case 2330 : + case 2340 : + case 2339 : + case 2341 : + case 2342 : + c.getDialogueHandler().sendDialogues(3530, npcType); + break; case 209: c.getDialogueHandler().sendDialogues(3500, 209); break; @@ -981,7 +1003,10 @@ public class NpcActions { } } switch (npcType) { - + case 3021 : + c.getFarmingTools().loadInterfaces(); + break; + case 3: c.getDialogueHandler().sendDialogues(5, npcType); break; diff --git a/2006Redone Server/src/main/java/com/rebotted/game/npcs/NpcHandler.java b/2006Redone Server/src/main/java/com/rebotted/game/npcs/NpcHandler.java index dd642907..fa97341f 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/npcs/NpcHandler.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/npcs/NpcHandler.java @@ -479,8 +479,41 @@ public class NpcHandler { if (npcs[i].npcType == 3782 && PestControl.gameStarted) { if (Misc.random(10) == 4) { - npcs[i].forceChat(voidKnightTalk[Misc - .random3(voidKnightTalk.length)]); + npcs[i].forceChat(voidKnightTalk[Misc.random3(voidKnightTalk.length)]); + } + } + + if (npcs[i].npcType == 162) { + if (npcs[i].getX() == 2475 && npcs[i].getY() == 3438) { + npcs[i].forceChat("Okay get over that log, quick quick!"); + } else if (npcs[i].getX() == 2471 && npcs[i].getY() == 3427) { + npcs[i].forceChat("Move it, move it, move it!"); + } else if (npcs[i].getX() == 2476 && npcs[i].getY() == 3423) { + npcs[i].forceChat("That's it - straight up"); + } else if (npcs[i].getX() == 2475 && npcs[i].getY() == 3421) { + if (Misc.random(1) == 0) { + npcs[i].forceChat("Terrorbirds could climb faster than that!"); + } else { + npcs[i].forceChat("Come on scaredy cat, get across that rope!"); + } + } else if (npcs[i].getX() == 2481 && npcs[i].getY() == 3424) { + npcs[i].forceChat("My Granny can move faster than you."); + } + } + + if (npcs[i].npcType == 43) { + if (Misc.random(20) == 4) { + npcs[i].forceChat("Baa!"); + } + } + if (npcs[i].npcType == 81 || npcs[i].npcType == 397 || npcs[i].npcType == 1766 || npcs[i].npcType == 1767 || npcs[i].npcType == 1768) { + if (Misc.random(30) == 4) { + npcs[i].forceChat("Moo"); + } + } + if (npcs[i].npcType == 45) { + if (Misc.random(30) == 6) { + npcs[i].forceChat("Quack!"); } } diff --git a/2006Redone Server/src/main/java/com/rebotted/game/objects/ObjectsActions.java b/2006Redone Server/src/main/java/com/rebotted/game/objects/ObjectsActions.java index 300aa7ba..b5802f18 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/objects/ObjectsActions.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/objects/ObjectsActions.java @@ -61,6 +61,10 @@ public class ObjectsActions { player.faceUpdate(0); player.clickObjectType = 0; player.turnPlayerTo(objectX, objectY); + player.getCompost().handleObjectClick(objectType, objectX, objectY); + if (Farming.harvest(player, objectX, objectY)) { + return; + } if (Webs.webs(player, objectType)) { Webs.slashWeb(player, objectType, objectX, objectY); return; @@ -2567,6 +2571,9 @@ public class ObjectsActions { Stalls.attemptStall(player, objectType, obX, obY); return; } + if (Farming.inspectObject(player, obX, obY)) { + return; + } switch (objectType) { case 6: player.getCannon().loadCannon(obX, obY); @@ -2870,8 +2877,6 @@ public class ObjectsActions { if (!Region.objectExists(objectType, obX, obY, player.heightLevel)) { return; } - Farming.openGuide(player, player.objectId); -// switch (objectType) { -// } + Farming.guide(player, obX, obY); } } diff --git a/2006Redone Server/src/main/java/com/rebotted/game/players/Player.java b/2006Redone Server/src/main/java/com/rebotted/game/players/Player.java index b9a83cb8..61a2490e 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/players/Player.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/players/Player.java @@ -44,6 +44,18 @@ import com.rebotted.game.content.skills.agility.WildernessAgility; import com.rebotted.game.content.skills.cooking.Potatoes; import com.rebotted.game.content.skills.core.Mining; import com.rebotted.game.content.skills.crafting.GlassBlowing; +import com.rebotted.game.content.skills.farming.Allotments; +import com.rebotted.game.content.skills.farming.Bushes; +import com.rebotted.game.content.skills.farming.Compost; +import com.rebotted.game.content.skills.farming.Flowers; +import com.rebotted.game.content.skills.farming.FruitTree; +import com.rebotted.game.content.skills.farming.Herbs; +import com.rebotted.game.content.skills.farming.Hops; +import com.rebotted.game.content.skills.farming.Seedling; +import com.rebotted.game.content.skills.farming.SpecialPlantOne; +import com.rebotted.game.content.skills.farming.SpecialPlantTwo; +import com.rebotted.game.content.skills.farming.ToolLeprechaun; +import com.rebotted.game.content.skills.farming.WoodTrees; import com.rebotted.game.content.skills.fletching.LogCuttingInterface; import com.rebotted.game.content.skills.runecrafting.Runecrafting; import com.rebotted.game.content.skills.slayer.Slayer; @@ -56,7 +68,8 @@ import com.rebotted.game.globalworldobjects.DoubleGates; import com.rebotted.game.globalworldobjects.GateHandler; import com.rebotted.game.globalworldobjects.SingleGates; import com.rebotted.game.items.GameItem; -import com.rebotted.game.items.Item; +import com.rebotted.game.items.Inventory; +import com.rebotted.game.items.ItemData; import com.rebotted.game.items.ItemAssistant; import com.rebotted.game.items.impl.PotionMixing; import com.rebotted.game.items.impl.Teles; @@ -80,6 +93,18 @@ import com.rebotted.world.ObjectManager; public abstract class Player { public byte buffer[] = null; + private Compost compost = new Compost(this); + private Allotments allotment = new Allotments(this); + private Flowers flower = new Flowers(this); + private Herbs herb = new Herbs(this); + private Hops hops = new Hops(this); + private Bushes bushes = new Bushes(this); + private Seedling seedling = new Seedling(this); + private WoodTrees trees = new WoodTrees(this); + private FruitTree fruitTrees = new FruitTree(this); + private SpecialPlantOne specialPlantOne = new SpecialPlantOne(this); + private SpecialPlantTwo specialPlantTwo = new SpecialPlantTwo(this); + private ToolLeprechaun toolLeprechaun = new ToolLeprechaun(this); public Stream inStream = null, outStream = null; public IoSession session; private final ItemAssistant itemAssistant = new ItemAssistant(this); @@ -135,6 +160,65 @@ public abstract class Player { private SingleGates singleGates = new SingleGates(); private DoubleGates doubleGates = new DoubleGates(); public int lastMainFrameInterface = -1; //Possibly used in future to prevent packet exploits + + public boolean isPreaching() { + return preaching; + } + + public void setPreaching(boolean preaching) { + this.preaching = preaching; + } + + public boolean preaching = false; + + public Compost getCompost() { + return compost; + } + + public Allotments getAllotment() { + return allotment; + } + + public Flowers getFlowers() { + return flower; + } + + public Herbs getHerbs() { + return herb; + } + + public Hops getHops() { + return hops; + } + + public Bushes getBushes() { + return bushes; + } + + public Seedling getSeedling() { + return seedling; + } + + public WoodTrees getTrees() { + return trees; + } + + public FruitTree getFruitTrees() { + return fruitTrees; + } + + public SpecialPlantOne getSpecialPlantOne() { + return specialPlantOne; + } + + public SpecialPlantTwo getSpecialPlantTwo() { + return specialPlantTwo; + } + + public ToolLeprechaun getFarmingTools() { + return toolLeprechaun; + } + public LogCuttingInterface getFletching() { return fletching; @@ -351,8 +435,31 @@ public abstract class Player { public Food getFood() { return food; } + + + public Inventory getInventory() { + return inventory; + } + + private Inventory inventory = new Inventory(this); + + + private int tempInteger; + public boolean tempBoolean = false; + + public void setTempInteger(int tempInteger) { + this.tempInteger = tempInteger; + } + + public int getTempInteger() { + return tempInteger; + } public int totalShopItems; + + public boolean stopPlayer(boolean stop) { + return (stop ? stopPlayerPacket == true : stopPlayerPacket == false); + } public boolean isSnowy; @@ -1265,7 +1372,7 @@ public abstract class Player { followId, skullTimer, nextChat = 0, talkingNpc = -1, dialogueAction = 0, autocastId, followDistance, followId2, barrageCount = 0, delayedDamage = 0, delayedDamage2 = 0, - pcPoints = 0, magePoints = 0, desertTreasure = 0, + pcPoints = 0, magePoints = 0, desertTreasure = 0, skillAmount, lastArrowUsed = -1, autoRet = 1, pcDamage = 0, xInterfaceId = 0, xRemoveId = 0, xRemoveSlot = 0, tzhaarToKill = 0, tzhaarKilled = 0, waveId, frozenBy = 0, poisonDamage = 0, teleAction = 0, @@ -2541,7 +2648,7 @@ public abstract class Player { playerProps.writeByte(0); } - if (!Item.isFullBody(playerEquipment[playerChest])) { + if (!ItemData.isFullBody(playerEquipment[playerChest])) { playerProps.writeWord(0x100 + playerAppearance[3]); } else { playerProps.writeByte(0); @@ -2553,8 +2660,8 @@ public abstract class Player { playerProps.writeWord(0x100 + playerAppearance[5]); } - if (!Item.isFullHelm(playerEquipment[playerHat]) - && !Item.isFullMask(playerEquipment[playerHat])) { + if (!ItemData.isFullHelm(playerEquipment[playerHat]) + && !ItemData.isFullMask(playerEquipment[playerHat])) { playerProps.writeWord(0x100 + playerAppearance[1]); } else { playerProps.writeByte(0); @@ -2573,7 +2680,7 @@ public abstract class Player { } if (playerAppearance[0] != 1 - && !Item.isFullMask(playerEquipment[playerHat])) { + && !ItemData.isFullMask(playerEquipment[playerHat])) { playerProps.writeWord(0x100 + playerAppearance[7]); } else { playerProps.writeByte(0); diff --git a/2006Redone Server/src/main/java/com/rebotted/game/players/Trading.java b/2006Redone Server/src/main/java/com/rebotted/game/players/Trading.java index daf98ec5..2a278196 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/players/Trading.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/players/Trading.java @@ -9,7 +9,7 @@ import com.rebotted.event.CycleEventContainer; import com.rebotted.event.CycleEventHandler; import com.rebotted.game.content.minigames.castlewars.CastleWars; import com.rebotted.game.items.GameItem; -import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemData; import com.rebotted.game.items.ItemAssistant; import com.rebotted.util.GameLogger; import com.rebotted.util.Misc; @@ -149,7 +149,7 @@ public class Trading { } player.tradeConfirmed = false; o.tradeConfirmed = false; - if (!Item.itemStackable[itemID]) { + if (!ItemData.itemStackable[itemID]) { for (int a = 0; a < amount; a++) { for (GameItem item : offeredItems) { if (item.id == itemID) { @@ -274,7 +274,7 @@ public class Trading { } player.tradeConfirmed = false; o.tradeConfirmed = false; - if (!Item.itemStackable[itemID] && !Item.itemIsNote[itemID]) { + if (!ItemData.itemStackable[itemID] && !ItemData.itemIsNote[itemID]) { for (int a = 0; a < amount && a < 28; a++) { if (player.getItemAssistant().playerHasItem(itemID, 1)) { offeredItems.add(new GameItem(itemID, 1)); @@ -306,7 +306,7 @@ public class Trading { declineTrade(); return false; } - if (Item.itemStackable[itemID] || Item.itemIsNote[itemID]) { + if (ItemData.itemStackable[itemID] || ItemData.itemIsNote[itemID]) { boolean inTrade = false; for (GameItem item : offeredItems) { if (item.id == itemID) { diff --git a/2006Redone Server/src/main/java/com/rebotted/game/shops/ShopAssistant.java b/2006Redone Server/src/main/java/com/rebotted/game/shops/ShopAssistant.java index 82b33889..2cf40ddf 100644 --- a/2006Redone Server/src/main/java/com/rebotted/game/shops/ShopAssistant.java +++ b/2006Redone Server/src/main/java/com/rebotted/game/shops/ShopAssistant.java @@ -2,7 +2,7 @@ package com.rebotted.game.shops; import com.rebotted.GameConstants; import com.rebotted.game.bots.BotHandler; -import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemData; import com.rebotted.game.items.ItemAssistant; import com.rebotted.game.items.ItemDefinition; import com.rebotted.game.players.Player; @@ -443,7 +443,7 @@ public class ShopAssistant { if (amount <= 0) { return false; } - if (Item.itemIsNote[itemID]) { + if (ItemData.itemIsNote[itemID]) { itemID = player.getItemAssistant().getUnnotedItem(itemID); } for (int i = 0; i < ShopHandler.shopItems[player.shopId].length; i++) { diff --git a/2006Redone Server/src/main/java/com/rebotted/net/PacketSender.java b/2006Redone Server/src/main/java/com/rebotted/net/PacketSender.java index 18222a3d..7164b790 100644 --- a/2006Redone Server/src/main/java/com/rebotted/net/PacketSender.java +++ b/2006Redone Server/src/main/java/com/rebotted/net/PacketSender.java @@ -8,6 +8,7 @@ import com.rebotted.game.content.combat.magic.MagicTeleports; import com.rebotted.game.content.quests.QuestAssistant; import com.rebotted.game.content.skills.SkillHandler; import com.rebotted.game.content.skills.runecrafting.Tiaras; +import com.rebotted.game.items.Item; import com.rebotted.game.items.ItemAssistant; import com.rebotted.game.items.Weight; import com.rebotted.game.items.impl.LightSources; @@ -26,6 +27,31 @@ public class PacketSender { this.player = player2; } + public PacketSender sendUpdateItems(int frame, Item[] items) { + player.getOutStream().createFrameVarSizeWord(53); + player.getOutStream().writeWord(frame); + player.getOutStream().writeWord(items.length); + Item[] var6 = items; + for (int i = 0; i < items.length; i++) { + Item item = var6[i]; + if (item == null) { + player.getOutStream().writeByte(0); + player.getOutStream().writeWordBigEndianA(0); + } else { + if (item.getCount() > 254) { + player.getOutStream().writeByte(255); + player.getOutStream().writeDWord_v2(item.getCount()); + } else { + player.getOutStream().writeByte(item.getCount()); + } + + player.getOutStream().writeWordBigEndianA(item.getId()); + } + } + return this; + } + + public PacketSender loginPlayer() { player.getPlayerAssistant().loginScreen(); if (Connection.isNamedBanned(player.playerName)) { diff --git a/2006Redone Server/src/main/java/com/rebotted/net/packets/PacketHandler.java b/2006Redone Server/src/main/java/com/rebotted/net/packets/PacketHandler.java index 70135216..05df9e3c 100644 --- a/2006Redone Server/src/main/java/com/rebotted/net/packets/PacketHandler.java +++ b/2006Redone Server/src/main/java/com/rebotted/net/packets/PacketHandler.java @@ -34,6 +34,7 @@ import com.rebotted.net.packets.impl.ItemOnObject; import com.rebotted.net.packets.impl.ItemOnPlayer; import com.rebotted.net.packets.impl.MagicOnFloorItems; import com.rebotted.net.packets.impl.MagicOnItems; +import com.rebotted.net.packets.impl.MagicOnObject; import com.rebotted.net.packets.impl.MoveItems; import com.rebotted.net.packets.impl.PickupItem; import com.rebotted.net.packets.impl.PrivateMessaging; @@ -112,6 +113,7 @@ public class PacketHandler { packetId[43] = new Bank10(); packetId[129] = new BankAll(); packetId[101] = new ChangeAppearance(); + packetId[35] = new MagicOnObject(); PrivateMessaging pm = new PrivateMessaging(); packetId[188] = pm; packetId[126] = pm; diff --git a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/BankAll.java b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/BankAll.java index c832b7a5..374ccdde 100644 --- a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/BankAll.java +++ b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/BankAll.java @@ -2,7 +2,7 @@ package com.rebotted.net.packets.impl; import com.rebotted.game.content.random.PartyRoom; import com.rebotted.game.items.GameItem; -import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemData; import com.rebotted.game.players.Player; import com.rebotted.net.packets.PacketType; @@ -61,7 +61,7 @@ public class BankAll implements PacketType { "You can't store items while trading!"); return; } - if (Item.itemStackable[removeId]) { + if (ItemData.itemStackable[removeId]) { player.getItemAssistant().bankItem(player.playerItems[removeSlot], removeSlot, player.playerItemsN[removeSlot]); } else { @@ -97,14 +97,14 @@ public class BankAll implements PacketType { case 3322: if (player.duelStatus <= 0) { - if (Item.itemStackable[removeId]) { + if (ItemData.itemStackable[removeId]) { player.getTrading().tradeItem(removeId, removeSlot, player.playerItemsN[removeSlot]); } else { player.getTrading().tradeItem(removeId, removeSlot, 28); } } else { - if (Item.itemStackable[removeId] || Item.itemIsNote[removeId]) { + if (ItemData.itemStackable[removeId] || ItemData.itemIsNote[removeId]) { player.getDueling().stakeItem(removeId, removeSlot, player.playerItemsN[removeSlot]); } else { @@ -115,7 +115,7 @@ public class BankAll implements PacketType { case 3415: if (player.duelStatus <= 0) { - if (Item.itemStackable[removeId]) { + if (ItemData.itemStackable[removeId]) { for (GameItem item : player.getTrading().offeredItems) { if (item.id == removeId) { player.getTrading() @@ -137,7 +137,7 @@ public class BankAll implements PacketType { break; case 6669: - if (Item.itemStackable[removeId] || Item.itemIsNote[removeId]) { + if (ItemData.itemStackable[removeId] || ItemData.itemIsNote[removeId]) { for (GameItem item : player.getDueling().stakedItems) { if (item.id == removeId) { player.getDueling() diff --git a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ClickItem.java b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ClickItem.java index 42d56a7f..2f8ae6a1 100644 --- a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ClickItem.java +++ b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ClickItem.java @@ -13,6 +13,7 @@ import com.rebotted.game.content.skills.woodcutting.BirdNest; import com.rebotted.game.items.ItemAssistant; import com.rebotted.game.items.impl.ExperienceLamp; import com.rebotted.game.items.impl.Flowers; +import com.rebotted.game.items.impl.GodBooks; import com.rebotted.game.players.Player; import com.rebotted.net.packets.PacketType; import com.rebotted.util.GameLogger; @@ -35,6 +36,7 @@ public class ClickItem implements PacketType { if(!player.getItemAssistant().playerHasItem(itemId, 1)) { return; } + GodBooks.sendPreachOptions(player, itemId); if (itemId == 6) { player.getCannon().placeCannon(); } diff --git a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ClickObject.java b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ClickObject.java index b10f2a91..2892707f 100644 --- a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ClickObject.java +++ b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ClickObject.java @@ -404,12 +404,9 @@ public class ClickObject implements PacketType { if (p.playerRights == 3) { p.getPacketSender().sendMessage("ObjectId: " + p.objectId + " ObjectX: " + p.objectX + " ObjectY: " + p.objectY + " Objectclick = 4, Xoff: " + (p.getX() - p.objectX) + " Yoff: " + (p.getY() - p.objectY)); } - + p.getObjects().fourthClickObject(p.objectId, p.objectX, p.objectY); break; } } - - - } diff --git a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/Commands.java b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/Commands.java index bfd26b40..f3c412d3 100644 --- a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/Commands.java +++ b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/Commands.java @@ -291,7 +291,11 @@ public class Commands implements PacketType { player.getPacketSender().showInterface(8134); break; case "stuck": - player.getPlayerAssistant().startTeleport(SpellTeleport.LUMBRIDGE.getDestX(), SpellTeleport.LUMBRIDGE.getDestY(), 0, "modern"); + if (player.getCombatAssistant().inCombat()) { + player.getPacketSender().sendMessage("You cannot do that while in combat."); + return; + } + player.getPlayerAssistant().movePlayer(SpellTeleport.LUMBRIDGE.getDestX(), SpellTeleport.LUMBRIDGE.getDestY(), 0); player.getPacketSender().sendMessage("How did you manage that one..."); player.getPacketSender().sendMessage("If it's bug related, please report on Github/Discord!"); player.gfx100(80); @@ -497,24 +501,6 @@ public class Commands implements PacketType { } public static void adminCommands(Player player, String playerCommand, String[] arguments) { - if (playerCommand.startsWith("getid")) { - String a[] = playerCommand.split(" "); - String itemName = ""; - int itemCount = 0; - for (int i = 1; i < a.length; i++) { - itemName = itemName + a[i]+ " "; - } - itemName = itemName.substring(0, itemName.length()-1); - player.getPacketSender().sendMessage("Searching: " + itemName); - for (int j = 0; j < GameEngine.itemHandler.ItemList.length; j++) { - if (GameEngine.itemHandler.ItemList[j] != null) - if (GameEngine.itemHandler.ItemList[j].itemName.replace("_", " ").toLowerCase().contains(itemName.toLowerCase())) { - player.getPacketSender().sendMessage("@dre@" + GameEngine.itemHandler.ItemList[j].itemName.replace("_", " ") + " - " + GameEngine.itemHandler.ItemList[j].itemId); - itemCount++; - } - } - player.getPacketSender().sendMessage(itemCount + " IDs found..."); - } switch (playerCommand.toLowerCase()) { case "clearbank": player.getItemAssistant().clearBank(); diff --git a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ItemOnNpc.java b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ItemOnNpc.java index dc1ab597..221bfff5 100644 --- a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ItemOnNpc.java +++ b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ItemOnNpc.java @@ -28,6 +28,11 @@ public class ItemOnNpc implements PacketType { } player.faceNpc(i); switch(npcId) { + case 3021: + if (player.getFarmingTools().noteItem(itemId)) { + return; + } + break; case 43: NpcHandler.npcs[i].shearSheep(player, 1735, 1737, 893, 43, 42, 50); break; diff --git a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ItemOnObject.java b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ItemOnObject.java index 176b53e1..6c15ca1c 100644 --- a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ItemOnObject.java +++ b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/ItemOnObject.java @@ -198,14 +198,6 @@ public class ItemOnObject implements PacketType { player.getPlayerAssistant().movePlayer(2510, 3096, 0); } - /* - * if (itemId == 1779 && objectId == 2644) { int amount = - * (c.getItemAssistant().getItemCount(1777)); int[] spin = {1777}; for - * (int i : spin) { c.getItemAssistant().deleteItem(i, - * c.getItemAssistant().getItemCount(i)); } c.startAnimation(883); - * c.getItemAssistant().addItem(1777, amount); } - */ - if (Fillables.canFill(itemId, objectId) && player.getItemAssistant().playerHasItem(itemId)) { int amount = player.getItemAssistant().getItemCount(itemId); player.getItemAssistant().deleteItem(itemId, amount); diff --git a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/MagicOnFloorItems.java b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/MagicOnFloorItems.java index 6d6aaa85..14c85f7d 100644 --- a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/MagicOnFloorItems.java +++ b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/MagicOnFloorItems.java @@ -5,7 +5,7 @@ import com.rebotted.event.CycleEvent; import com.rebotted.event.CycleEventContainer; import com.rebotted.event.CycleEventHandler; import com.rebotted.game.content.combat.magic.MagicData; -import com.rebotted.game.items.Item; +import com.rebotted.game.items.ItemData; import com.rebotted.game.players.Player; import com.rebotted.net.packets.PacketType; @@ -35,9 +35,9 @@ public class MagicOnFloorItems implements PacketType { if ((c.getItemAssistant().freeSlots() >= 1 || c.getItemAssistant() .playerHasItem(itemId, 1)) - && Item.itemStackable[itemId] + && ItemData.itemStackable[itemId] || c.getItemAssistant().freeSlots() > 0 - && !Item.itemStackable[itemId]) { + && !ItemData.itemStackable[itemId]) { if (c.goodDistance(c.getX(), c.getY(), itemX, itemY, 12)) { c.walkingToItem = true; int offY = (c.getX() - itemX) * -1; diff --git a/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/MagicOnObject.java b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/MagicOnObject.java new file mode 100644 index 00000000..5a6547cb --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/net/packets/impl/MagicOnObject.java @@ -0,0 +1,27 @@ +package com.rebotted.net.packets.impl; + +import com.rebotted.game.content.skills.crafting.OrbCharging; +import com.rebotted.game.players.Player; +import com.rebotted.net.packets.PacketType; + +public class MagicOnObject implements PacketType { + + @Override + public void processPacket(Player player, int packetType, int packetSize) { + int x = player.getInStream().readSignedWordBigEndian(); + int magicId = player.getInStream().readUnsignedWord(); + int y = player.getInStream().readUnsignedWordA(); + int objectId = player.getInStream().readSignedWordBigEndian(); + + player.turnPlayerTo(x, y); + switch (objectId) { + case 2153: + case 2152: + case 2151: + case 2150: + OrbCharging.chargeOrbs(player, magicId, objectId); + break; + } + } + +} diff --git a/2006Redone Server/src/main/java/com/rebotted/tick/Scheduler.java b/2006Redone Server/src/main/java/com/rebotted/tick/Scheduler.java new file mode 100644 index 00000000..fa7ab4f5 --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/tick/Scheduler.java @@ -0,0 +1,59 @@ +package com.rebotted.tick; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Queue; + +/** + * A class which schedules the execution of {@link Tick}s. + * + * @author Graham + */ +public final class Scheduler { + + /** + * A list of active ticks. + */ + private final List ticks = new ArrayList(); + + /** + * A queue of ticks that still need to be added. + */ + private final Queue newTicks = new ArrayDeque(); + + /** + * Schedules the specified tick. + * + * @param tick + * The tick to schedule. + */ + public void schedule(final Tick tick) { + synchronized (newTicks) { + newTicks.add(tick); + } + } + + /** + * This method is called every cycle and executes, adds and removes + * {@link Tick}s. + */ + public void process() { + synchronized (newTicks) { + Tick tick; + while ((tick = newTicks.poll()) != null) + ticks.add(tick); + } + + for (Iterator it = ticks.iterator(); it.hasNext();) { + Tick tick = it.next(); + try { + if (!tick.tick()) + it.remove(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/2006Redone Server/src/main/java/com/rebotted/tick/Tick.java b/2006Redone Server/src/main/java/com/rebotted/tick/Tick.java new file mode 100644 index 00000000..541fd00c --- /dev/null +++ b/2006Redone Server/src/main/java/com/rebotted/tick/Tick.java @@ -0,0 +1,151 @@ +package com.rebotted.tick; + +/** + * Represents a periodic task that can be scheduled with a {@link Scheduler}. + * + * @author Graham + */ +public abstract class Tick { + + /** + * The number of cycles between consecutive executions of this task. + */ + private final int delay; + + /** + * The current 'count down' value. When this reaches zero the task will be + * executed. + */ + private int countdown; + + /** + * A flag which indicates if this task is still running. + */ + private boolean running = true; + + /** + * Creates a new task with the specified delay. + * + * @param delay + * The number of cycles between consecutive executions of this + * task. + * @throws IllegalArgumentException + * if the {@code delay} is not positive. + */ + public Tick(int delay) { + checkDelay(delay); + this.delay = delay; + this.countdown = delay; + } + + /** + * Checks if the task is running. + * + * @return {@code true} if so, {@code false} if not. + */ + public boolean isRunning() { + return running; + } + + /** + * Checks if the task is stopped. + * + * @return {@code true} if so, {@code false} if not. + */ + public boolean isStopped() { + return !running; + } + + /** + * This method should be called by the scheduling class every cycle. It + * updates the {@link #countdown} and calls the {@link #execute()} method if + * necessary. + * + * @return A flag indicating if the task is running. + */ + public boolean tick() { + if (running && --countdown == 0) { + execute(); + countdown = delay; + } + return running; + } + + public int getCountdown() { + return countdown; + } + + /** + * Performs this task's action. + */ + protected abstract void execute(); + + /** + * Changes the delay of this task. + * + * @param delay + * The number of cycles between consecutive executions of this + * task. + * @throws IllegalArgumentException + * if the {@code delay} is not positive. + */ + public void setDelay(int delay) { + checkDelay(delay); + delay = 0; + } + + /** + * Stops this task. + * + * @throws IllegalStateException + * if the task has already been stopped. + */ + public void stop() { + if (!checkStopped()) + return; + running = false; + onStop(); + } + + /** + * Stops this task. Does not run the onStop method. + * + * @throws IllegalStateException + * if the task has already been stopped. + */ + public void forceStop() { + checkStopped(); + running = false; + } + + /** + * Override this method for code which should be run when the task stops. + */ + public void onStop() { + + } + + /** + * Checks if the delay is negative and throws an exception if so. + * + * @param delay + * The delay. + * @throws IllegalArgumentException + * if the delay is not positive. + */ + private void checkDelay(int delay) { + if (delay < 0) + throw new IllegalArgumentException("Delay must be positive."); + } + + /** + * Checks if this task has been stopped and throws an exception if so. + * + * @throws IllegalStateException + * if the task has been stopped. + */ + private boolean checkStopped() { + return running; + } + +} \ No newline at end of file diff --git a/2006Redone Server/src/main/java/com/rebotted/world/ItemHandler.java b/2006Redone Server/src/main/java/com/rebotted/world/ItemHandler.java index b7d97a15..66fbb696 100644 --- a/2006Redone Server/src/main/java/com/rebotted/world/ItemHandler.java +++ b/2006Redone Server/src/main/java/com/rebotted/world/ItemHandler.java @@ -169,7 +169,7 @@ public int itemAmount(String name, int itemId, int itemX, int itemY) { } } } - if (!com.rebotted.game.items.Item.itemStackable[itemId] && itemAmount > 0) { + if (!com.rebotted.game.items.ItemData.itemStackable[itemId] && itemAmount > 0) { for (int j = 0; j < itemAmount; j++) { c.getPacketSender().createGroundItem(itemId, itemX, itemY, 1); GroundItem item = new GroundItem(itemId, itemX, itemY, c.getH(), 1, c.playerId, HIDE_TICKS, PlayerHandler.players[playerId].playerName);