| @@ -0,0 +1,745 @@ | |||
| 1 | + | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | + | <spells> | |
| 3 | + | <instant group="attack" spellid="62" name="Annihilation" words="exori gran ico" lvl="110" mana="300" prem="1" range="1" needtarget="1" blockwalls="1" needweapon="1" exhaustion="30000" groupcooldown="4000" needlearn="0" script="attack/annihilation.lua"> | |
| 4 | + | <vocation name="Knight" /> | |
| 5 | + | <vocation name="Elite Knight" /> | |
| 6 | + | </instant> | |
| 7 | + | <instant group="attack" spellid="169" name="Apprentice's Strike" words="exori min flam" lvl="8" mana="6" prem="0" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="attack/apprentices strike.lua"> | |
| 8 | + | <vocation name="Sorcerer" /> | |
| 9 | + | <vocation name="Druid" /> | |
| 10 | + | <vocation name="Master Sorcerer" /> | |
| 11 | + | <vocation name="Elder Druid" /> | |
| 12 | + | </instant> | |
| 13 | + | <instant group="attack" spellid="80" name="Berserk" words="exori" lvl="35" mana="115" prem="1" needweapon="1" exhaustion="4000" groupcooldown="2000" needlearn="0" script="attack/berserk.lua"> | |
| 14 | + | <vocation name="Knight" /> | |
| 15 | + | <vocation name="Elite Knight" /> | |
| 16 | + | </instant> | |
| 17 | + | <instant group="support" spellid="133" name="Blood Rage" words="utito tempo" lvl="60" mana="290" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/blood rage.lua"> | |
| 18 | + | <vocation name="Knight" /> | |
| 19 | + | <vocation name="Elite Knight" /> | |
| 20 | + | </instant> | |
| 21 | + | <instant group="attack" spellid="61" name="Brutal Strike" words="exori ico" lvl="16" mana="30" prem="1" range="1" needtarget="1" blockwalls="1" needweapon="1" exhaustion="6000" groupcooldown="2000" needlearn="0" script="attack/brutal strike.lua"> | |
| 22 | + | <vocation name="Knight" /> | |
| 23 | + | <vocation name="Elite Knight" /> | |
| 24 | + | </instant> | |
| 25 | + | <instant group="support" spellid="90" name="Cancel Invisibility" words="exana ina" lvl="26" mana="200" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/cancel invisibility.lua"> | |
| 26 | + | <vocation name="Paladin" /> | |
| 27 | + | <vocation name="Royal Paladin" /> | |
| 28 | + | </instant> | |
| 29 | + | <instant group="support" spellid="93" name="Challenge" words="exeta res" lvl="20" mana="30" prem="1" aggressive="0" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/challenge.lua"> | |
| 30 | + | <vocation name="Elite Knight" /> | |
| 31 | + | </instant> | |
| 32 | + | <instant group="support" spellid="131" name="Charge" words="utani tempo hur" lvl="25" mana="100" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/charge.lua"> | |
| 33 | + | <vocation name="Knight" /> | |
| 34 | + | <vocation name="Elite Knight" /> | |
| 35 | + | </instant> | |
| 36 | + | <instant group="support" spellid="38" name="Creature Illusion" words="utevo res ina" lvl="23" mana="100" aggressive="0" params="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="Illusion"> | |
| 37 | + | <vocation name="Sorcerer" /> | |
| 38 | + | <vocation name="Druid" /> | |
| 39 | + | <vocation name="Master Sorcerer" /> | |
| 40 | + | <vocation name="Elder Druid" /> | |
| 41 | + | </instant> | |
| 42 | + | <instant group="healing" spellid="144" name="Cure Bleeding" words="exana kor" lvl="45" mana="30" aggressive="0" selftarget="1" exhaustion="6000" groupcooldown="1000" needlearn="0" script="healing/cure bleeding.lua"> | |
| 43 | + | <vocation name="Druid" /> | |
| 44 | + | <vocation name="Knight" /> | |
| 45 | + | <vocation name="Elder Druid" /> | |
| 46 | + | <vocation name="Elite Knight" /> | |
| 47 | + | </instant> | |
| 48 | + | <instant group="healing" spellid="145" name="Cure Burning" words="exana flam" lvl="30" mana="30" aggressive="0" selftarget="1" exhaustion="6000" groupcooldown="1000" needlearn="0" script="healing/cure burning.lua"> | |
| 49 | + | <vocation name="Druid" /> | |
| 50 | + | <vocation name="Elder Druid" /> | |
| 51 | + | </instant> | |
| 52 | + | <instant group="healing" spellid="147" name="Cure Curse" words="exana mort" lvl="80" mana="40" aggressive="0" selftarget="1" exhaustion="6000" groupcooldown="1000" needlearn="0" script="healing/cure curse.lua"> | |
| 53 | + | <vocation name="Paladin" /> | |
| 54 | + | <vocation name="Royal Paladin" /> | |
| 55 | + | </instant> | |
| 56 | + | <instant group="healing" spellid="146" name="Cure Electrification" words="exana vis" lvl="22" mana="30" aggressive="0" selftarget="1" exhaustion="6000" groupcooldown="1000" needlearn="0" script="healing/cure electrification.lua"> | |
| 57 | + | <vocation name="Druid" /> | |
| 58 | + | <vocation name="Elder Druid" /> | |
| 59 | + | </instant> | |
| 60 | + | <instant group="healing" spellid="29" name="Cure Poison" words="exana pox" lvl="10" mana="30" aggressive="0" selftarget="1" exhaustion="6000" groupcooldown="1000" needlearn="0" script="healing/antidote.lua"> | |
| 61 | + | <vocation name="Sorcerer" /> | |
| 62 | + | <vocation name="Druid" /> | |
| 63 | + | <vocation name="Paladin" /> | |
| 64 | + | <vocation name="Knight" /> | |
| 65 | + | <vocation name="Master Sorcerer" /> | |
| 66 | + | <vocation name="Elder Druid" /> | |
| 67 | + | <vocation name="Royal Paladin" /> | |
| 68 | + | <vocation name="Elite Knight" /> | |
| 69 | + | </instant> | |
| 70 | + | <instant group="attack" spellid="139" name="Curse" words="utori mort" lvl="75" mana="30" range="3" aggressive="1" blockwalls="1" needtarget="1" exhaustion="50000" groupcooldown="2000" needlearn="0" script="attack/curse.lua"> | |
| 71 | + | <vocation name="Sorcerer" /> | |
| 72 | + | <vocation name="Master Sorcerer" /> | |
| 73 | + | </instant> | |
| 74 | + | <instant group="attack" spellid="87" name="Death Strike" words="exori mort" lvl="16" mana="20" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="attack/death strike.lua"> | |
| 75 | + | <vocation name="Sorcerer" /> | |
| 76 | + | <vocation name="Master Sorcerer" /> | |
| 77 | + | </instant> | |
| 78 | + | <instant group="attack" spellid="124" name="Divine Caldera" words="exevo mas san" lvl="50" mana="160" prem="1" selftarget="1" exhaustion="4000" groupcooldown="2000" needlearn="0" script="attack/divine caldera.lua"> | |
| 79 | + | <vocation name="Paladin" /> | |
| 80 | + | <vocation name="Royal Paladin" /> | |
| 81 | + | </instant> | |
| 82 | + | <instant group="healing" spellid="125" name="Divine Healing" words="exura san" lvl="35" mana="160" prem="0" selftarget="1" aggressive="0" exhaustion="1000" groupcooldown="1000" needlearn="0" script="healing/divine healing.lua"> | |
| 83 | + | <vocation name="Paladin" /> | |
| 84 | + | <vocation name="Royal Paladin" /> | |
| 85 | + | </instant> | |
| 86 | + | <instant group="attack" spellid="122" name="Divine Missile" words="exori san" lvl="40" mana="20" prem="1" range="4" casterTargetOrDirection="1" needlearn="0" blockwalls="1" exhaustion="2000" groupcooldown="2000" script="attack/divine missile.lua"> | |
| 87 | + | <vocation name="Paladin" /> | |
| 88 | + | <vocation name="Royal Paladin" /> | |
| 89 | + | </instant> | |
| 90 | + | <instant group="attack" spellid="140" name="Electrify" words="utori vis" lvl="34" mana="30" range="3" aggressive="1" blockwalls="1" needtarget="1" exhaustion="30000" groupcooldown="2000" needlearn="0" script="attack/electrify.lua"> | |
| 91 | + | <vocation name="Sorcerer" /> | |
| 92 | + | <vocation name="Master Sorcerer" /> | |
| 93 | + | </instant> | |
| 94 | + | <instant group="support" spellid="129" name="Enchant Party" words="utori mas sio" lvl="32" mana="120" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="party/enchant.lua"> | |
| 95 | + | <vocation name="Sorcerer" /> | |
| 96 | + | <vocation name="Master Sorcerer" /> | |
| 97 | + | </instant> | |
| 98 | + | <instant group="attack" spellid="22" name="Energy Beam" words="exevo vis lux" lvl="23" mana="40" direction="1" exhaustion="4000" groupcooldown="2000" needlearn="0" script="attack/energy beam.lua"> | |
| 99 | + | <vocation name="Sorcerer" /> | |
| 100 | + | <vocation name="Master Sorcerer" /> | |
| 101 | + | </instant> | |
| 102 | + | <instant group="attack" spellid="88" name="Energy Strike" words="exori vis" lvl="12" mana="20" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="attack/energy strike.lua"> | |
| 103 | + | <vocation name="Sorcerer" /> | |
| 104 | + | <vocation name="Druid" /> | |
| 105 | + | <vocation name="Master Sorcerer" /> | |
| 106 | + | <vocation name="Elder Druid" /> | |
| 107 | + | </instant> | |
| 108 | + | <instant group="attack" spellid="13" name="Energy Wave" words="exevo vis hur" lvl="38" mana="170" direction="1" exhaustion="8000" groupcooldown="2000" needlearn="0" script="attack/energy wave.lua"> | |
| 109 | + | <vocation name="Sorcerer" /> | |
| 110 | + | <vocation name="Master Sorcerer" /> | |
| 111 | + | </instant> | |
| 112 | + | <instant group="attack" spellid="142" name="Envenom" words="utori pox" lvl="50" mana="30" range="3" aggressive="1" blockwalls="1" needtarget="1" exhaustion="40000" groupcooldown="2000" needlearn="0" script="attack/envenom.lua"> | |
| 113 | + | <vocation name="Druid" /> | |
| 114 | + | <vocation name="Elder Druid" /> | |
| 115 | + | </instant> | |
| 116 | + | <instant group="attack" spellid="118" name="Eternal Winter" words="exevo gran mas frigo" lvl="60" mana="1050" prem="1" selftarget="1" exhaustion="40000" groupcooldown="4000" needlearn="0" script="attack/eternal winter.lua"> | |
| 117 | + | <vocation name="Druid" /> | |
| 118 | + | <vocation name="Elder Druid" /> | |
| 119 | + | </instant> | |
| 120 | + | <instant group="attack" spellid="111" name="Ethereal Spear" words="exori con" lvl="23" mana="25" prem="1" range="7" needtarget="1" exhaustion="2000" groupcooldown="2000" blockwalls="1" needlearn="0" script="attack/ethereal spear.lua"> | |
| 121 | + | <vocation name="Paladin" /> | |
| 122 | + | <vocation name="Royal Paladin" /> | |
| 123 | + | </instant> | |
| 124 | + | <instant group="attack" spellid="105" name="Fierce Berserk" words="exori gran" lvl="90" mana="340" prem="1" needweapon="1" exhaustion="6000" groupcooldown="2000" needlearn="0" script="attack/fierce berserk.lua"> | |
| 125 | + | <vocation name="Knight" /> | |
| 126 | + | <vocation name="Elite Knight" /> | |
| 127 | + | </instant> | |
| 128 | + | <instant group="support" spellid="20" name="Find Person" words="exiva" lvl="8" mana="20" aggressive="0" playernameparam="1" params="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="searchPlayer"> | |
| 129 | + | <vocation name="Sorcerer" /> | |
| 130 | + | <vocation name="Druid" /> | |
| 131 | + | <vocation name="Paladin" /> | |
| 132 | + | <vocation name="Knight" /> | |
| 133 | + | <vocation name="Master Sorcerer" /> | |
| 134 | + | <vocation name="Elder Druid" /> | |
| 135 | + | <vocation name="Royal Paladin" /> | |
| 136 | + | <vocation name="Elite Knight" /> | |
| 137 | + | </instant> | |
| 138 | + | <instant group="attack" spellid="19" name="Fire Wave" words="exevo flam hur" lvl="18" mana="25" direction="1" exhaustion="4000" groupcooldown="2000" needlearn="0" script="attack/fire wave.lua"> | |
| 139 | + | <vocation name="Sorcerer" /> | |
| 140 | + | <vocation name="Master Sorcerer" /> | |
| 141 | + | </instant> | |
| 142 | + | <instant group="attack" spellid="89" name="Flame Strike" words="exori flam" lvl="14" mana="20" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="attack/flame strike.lua"> | |
| 143 | + | <vocation name="Sorcerer" /> | |
| 144 | + | <vocation name="Druid" /> | |
| 145 | + | <vocation name="Master Sorcerer" /> | |
| 146 | + | <vocation name="Elder Druid" /> | |
| 147 | + | </instant> | |
| 148 | + | <instant group="support" spellid="42" name="Food" words="exevo pan" lvl="14" mana="120" soul="1" exhaustion="2000" groupcooldown="2000" aggressive="0" needlearn="0" script="support/food.lua"> | |
| 149 | + | <vocation name="Druid" /> | |
| 150 | + | <vocation name="Elder Druid" /> | |
| 151 | + | </instant> | |
| 152 | + | <instant group="attack" spellid="59" name="Front Sweep" words="exori min" lvl="70" mana="200" prem="1" needweapon="1" direction="1" exhaustion="6000" groupcooldown="2000" needlearn="0" script="attack/front sweep.lua"> | |
| 153 | + | <vocation name="Knight" /> | |
| 154 | + | <vocation name="Elite Knight" /> | |
| 155 | + | </instant> | |
| 156 | + | <instant group="attack" spellid="23" name="Great Energy Beam" words="exevo gran vis lux" lvl="29" mana="110" direction="1" exhaustion="6000" groupcooldown="2000" needlearn="0" script="attack/great energy beam.lua"> | |
| 157 | + | <vocation name="Sorcerer" /> | |
| 158 | + | <vocation name="Master Sorcerer" /> | |
| 159 | + | </instant> | |
| 160 | + | <instant group="support" spellid="11" name="Great Light" words="utevo gran lux" lvl="13" mana="60" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/great light.lua"> | |
| 161 | + | <vocation name="Sorcerer" /> | |
| 162 | + | <vocation name="Druid" /> | |
| 163 | + | <vocation name="Paladin" /> | |
| 164 | + | <vocation name="Knight" /> | |
| 165 | + | <vocation name="Master Sorcerer" /> | |
| 166 | + | <vocation name="Elder Druid" /> | |
| 167 | + | <vocation name="Royal Paladin" /> | |
| 168 | + | <vocation name="Elite Knight" /> | |
| 169 | + | </instant> | |
| 170 | + | <instant group="attack" spellid="106" name="Groundshaker" words="exori mas" lvl="33" mana="160" prem="1" needweapon="1" exhaustion="8000" groupcooldown="2000" needlearn="0" script="attack/groundshaker.lua"> | |
| 171 | + | <vocation name="Knight" /> | |
| 172 | + | <vocation name="Elite Knight" /> | |
| 173 | + | </instant> | |
| 174 | + | <instant group="support" spellid="6" name="Haste" words="utani hur" lvl="14" mana="60" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/haste.lua"> | |
| 175 | + | <vocation name="Sorcerer" /> | |
| 176 | + | <vocation name="Druid" /> | |
| 177 | + | <vocation name="Paladin" /> | |
| 178 | + | <vocation name="Knight" /> | |
| 179 | + | <vocation name="Master Sorcerer" /> | |
| 180 | + | <vocation name="Elder Druid" /> | |
| 181 | + | <vocation name="Royal Paladin" /> | |
| 182 | + | <vocation name="Elite Knight" /> | |
| 183 | + | </instant> | |
| 184 | + | <instant group="healing" spellid="84" name="Heal Friend" words="exura sio" lvl="18" mana="140" prem="1" aggressive="0" blockwalls="1" needtarget="1" playernameparam="1" params="1" exhaustion="1000" groupcooldown="1000" needlearn="0" script="healing/heal friend.lua"> | |
| 185 | + | <vocation name="Druid" /> | |
| 186 | + | <vocation name="Elder Druid" /> | |
| 187 | + | </instant> | |
| 188 | + | <instant group="support" spellid="128" name="Heal Party" words="utura mas sio" lvl="32" mana="120" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="party/heal.lua"> | |
| 189 | + | <vocation name="Druid" /> | |
| 190 | + | <vocation name="Elder Druid" /> | |
| 191 | + | </instant> | |
| 192 | + | <instant group="attack" spellid="24" name="Hell's Core" words="exevo gran mas flam" lvl="60" mana="1100" prem="1" exhaustion="40000" groupcooldown="4000" selftarget="1" needlearn="0" script="attack/hells core.lua"> | |
| 193 | + | <vocation name="Sorcerer" /> | |
| 194 | + | <vocation name="Master Sorcerer" /> | |
| 195 | + | </instant> | |
| 196 | + | <instant group="attack" spellid="143" name="Holy Flash" words="utori san" lvl="70" mana="30" range="3" aggressive="1" blockwalls="1" needtarget="1" exhaustion="40000" groupcooldown="2000" needlearn="0" script="attack/holy flash.lua"> | |
| 197 | + | <vocation name="Paladin" /> | |
| 198 | + | <vocation name="Royal Paladin" /> | |
| 199 | + | </instant> | |
| 200 | + | <instant group="attack" spellid="112" name="Ice Strike" words="exori frigo" lvl="15" mana="20" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="attack/ice strike.lua"> | |
| 201 | + | <vocation name="Sorcerer" /> | |
| 202 | + | <vocation name="Master Sorcerer" /> | |
| 203 | + | <vocation name="Druid" /> | |
| 204 | + | <vocation name="Elder Druid" /> | |
| 205 | + | </instant> | |
| 206 | + | <instant group="attack" spellid="121" name="Ice Wave" words="exevo frigo hur" lvl="18" mana="25" direction="1" exhaustion="4000" groupcooldown="2000" needlearn="0" script="attack/ice wave.lua"> | |
| 207 | + | <vocation name="Druid" /> | |
| 208 | + | <vocation name="Elder Druid" /> | |
| 209 | + | </instant> | |
| 210 | + | <instant group="attack" spellid="138" name="Ignite" words="utori flam" lvl="26" mana="30" range="3" aggressive="1" blockwalls="1" needtarget="1" exhaustion="30000" groupcooldown="2000" needlearn="0" script="attack/ignite.lua"> | |
| 211 | + | <vocation name="Sorcerer" /> | |
| 212 | + | <vocation name="Master Sorcerer" /> | |
| 213 | + | </instant> | |
| 214 | + | <instant group="attack" spellid="141" name="Inflict Wound" words="utori kor" lvl="40" mana="30" range="1" aggressive="1" blockwalls="1" needtarget="1" exhaustion="30000" groupcooldown="2000" needlearn="0" script="attack/inflict wound.lua"> | |
| 215 | + | <vocation name="Knight" /> | |
| 216 | + | <vocation name="Elite Knight" /> | |
| 217 | + | </instant> | |
| 218 | + | <instant group="healing" spellid="2" name="Intense Healing" words="exura gran" lvl="20" mana="70" aggressive="0" selftarget="1" exhaustion="1000" groupcooldown="1000" needlearn="0" script="healing/intense healing.lua"> | |
| 219 | + | <vocation name="Sorcerer" /> | |
| 220 | + | <vocation name="Druid" /> | |
| 221 | + | <vocation name="Paladin" /> | |
| 222 | + | <vocation name="Master Sorcerer" /> | |
| 223 | + | <vocation name="Elder Druid" /> | |
| 224 | + | <vocation name="Royal Paladin" /> | |
| 225 | + | </instant> | |
| 226 | + | <instant group="healing" spellid="160" name="Intense Recovery" words="utura gran" lvl="100" mana="165" aggressive="0" selftarget="1" exhaustion="60000" groupcooldown="1000" needlearn="0" script="healing/intense recovery.lua"> | |
| 227 | + | <vocation name="Paladin" /> | |
| 228 | + | <vocation name="Knight" /> | |
| 229 | + | <vocation name="Royal Paladin" /> | |
| 230 | + | <vocation name="Elite Knight" /> | |
| 231 | + | </instant> | |
| 232 | + | <instant group="healing" spellid="158" name="Intense Wound Cleansing" words="exura gran ico" lvl="80" mana="200" prem="1" selftarget="1" aggressive="0" exhaustion="600000" groupcooldown="1000" needlearn="0" script="healing/intense wound cleansing.lua"> | |
| 233 | + | <vocation name="Knight" /> | |
| 234 | + | <vocation name="Elite Knight" /> | |
| 235 | + | </instant> | |
| 236 | + | <instant group="support" spellid="45" name="Invisibility" words="utana vid" lvl="35" mana="440" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/invisible.lua"> | |
| 237 | + | <vocation name="Sorcerer" /> | |
| 238 | + | <vocation name="Druid" /> | |
| 239 | + | <vocation name="Master Sorcerer" /> | |
| 240 | + | <vocation name="Elder Druid" /> | |
| 241 | + | </instant> | |
| 242 | + | <instant group="support" spellid="81" name="Levitate" words="exani hur" lvl="12" mana="50" prem="1" aggressive="0" exhaustion="2000" groupcooldown="2000" params="1" needlearn="0" function="Levitate"> | |
| 243 | + | <vocation name="Sorcerer" /> | |
| 244 | + | <vocation name="Druid" /> | |
| 245 | + | <vocation name="Paladin" /> | |
| 246 | + | <vocation name="Knight" /> | |
| 247 | + | <vocation name="Master Sorcerer" /> | |
| 248 | + | <vocation name="Elder Druid" /> | |
| 249 | + | <vocation name="Royal Paladin" /> | |
| 250 | + | <vocation name="Elite Knight" /> | |
| 251 | + | </instant> | |
| 252 | + | <instant group="support" spellid="10" name="Light" words="utevo lux" lvl="8" mana="20" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/light.lua"> | |
| 253 | + | <vocation name="Sorcerer" /> | |
| 254 | + | <vocation name="Druid" /> | |
| 255 | + | <vocation name="Paladin" /> | |
| 256 | + | <vocation name="Knight" /> | |
| 257 | + | <vocation name="Master Sorcerer" /> | |
| 258 | + | <vocation name="Elder Druid" /> | |
| 259 | + | <vocation name="Royal Paladin" /> | |
| 260 | + | <vocation name="Elite Knight" /> | |
| 261 | + | </instant> | |
| 262 | + | <instant group="healing" spellid="1" name="Light Healing" words="exura" lvl="8" mana="20" aggressive="0" selftarget="1" exhaustion="1000" groupcooldown="1000" needlearn="0" script="healing/light healing.lua"> | |
| 263 | + | <vocation name="Sorcerer" /> | |
| 264 | + | <vocation name="Druid" /> | |
| 265 | + | <vocation name="Paladin" /> | |
| 266 | + | <vocation name="Master Sorcerer" /> | |
| 267 | + | <vocation name="Elder Druid" /> | |
| 268 | + | <vocation name="Royal Paladin" /> | |
| 269 | + | </instant> | |
| 270 | + | <instant group="attack" spellid="149" name="Lightning" words="exori amp vis" lvl="55" mana="60" prem="1" range="4" casterTargetOrDirection="1" blockwalls="1" exhaustion="8000" groupcooldown="2000" needlearn="0" script="attack/lightning.lua"> | |
| 271 | + | <vocation name="Sorcerer" /> | |
| 272 | + | <vocation name="Master Sorcerer" /> | |
| 273 | + | </instant> | |
| 274 | + | <instant group="support" spellid="76" name="Magic Rope" words="exani tera" lvl="9" mana="20" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/magic rope.lua"> | |
| 275 | + | <vocation name="Sorcerer" /> | |
| 276 | + | <vocation name="Druid" /> | |
| 277 | + | <vocation name="Paladin" /> | |
| 278 | + | <vocation name="Knight" /> | |
| 279 | + | <vocation name="Master Sorcerer" /> | |
| 280 | + | <vocation name="Elder Druid" /> | |
| 281 | + | <vocation name="Royal Paladin" /> | |
| 282 | + | <vocation name="Elite Knight" /> | |
| 283 | + | </instant> | |
| 284 | + | <instant group="support" spellid="44" name="Magic Shield" words="utamo vita" lvl="14" mana="50" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/magic shield.lua"> | |
| 285 | + | <vocation name="Sorcerer" /> | |
| 286 | + | <vocation name="Druid" /> | |
| 287 | + | <vocation name="Master Sorcerer" /> | |
| 288 | + | <vocation name="Elder Druid" /> | |
| 289 | + | </instant> | |
| 290 | + | <instant group="healing" spellid="82" name="Mass Healing" words="exura gran mas res" lvl="36" mana="150" prem="1" aggressive="0" exhaustion="2000" groupcooldown="1000" needlearn="0" script="healing/mass healing.lua"> | |
| 291 | + | <vocation name="Druid" /> | |
| 292 | + | <vocation name="Elder Druid" /> | |
| 293 | + | </instant> | |
| 294 | + | <instant group="attack" spellid="148" name="Physical Strike" words="exori moe ico" lvl="16" mana="20" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="attack/physical strike.lua"> | |
| 295 | + | <vocation name="Druid" /> | |
| 296 | + | <vocation name="Elder Druid" /> | |
| 297 | + | </instant> | |
| 298 | + | <instant group="attack" spellid="167" name="Practise Fire Wave" words="exevo dis flam hur" lvl="1" mana="5" direction="1" exhaustion="4000" groupcooldown="2000" needlearn="0" script="attack/practise fire wave.lua"> | |
| 299 | + | <vocation name="None" /> | |
| 300 | + | </instant> | |
| 301 | + | <instant group="healing" spellid="166" name="Practise Healing" words="exura dis" lvl="1" mana="5" aggressive="0" selftarget="1" exhaustion="1000" groupcooldown="1000" needlearn="0" script="healing/practise healing.lua"> | |
| 302 | + | <vocation name="None" /> | |
| 303 | + | </instant> | |
| 304 | + | <instant group="support" spellid="127" name="Protect Party" words="utamo mas sio" lvl="32" mana="90" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="party/protect.lua"> | |
| 305 | + | <vocation name="Paladin" /> | |
| 306 | + | <vocation name="Royal Paladin" /> | |
| 307 | + | </instant> | |
| 308 | + | <instant group="support" spellid="132" name="Protector" words="utamo tempo" lvl="55" mana="200" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/protector.lua"> | |
| 309 | + | <vocation name="Knight" /> | |
| 310 | + | <vocation name="Elite Knight" /> | |
| 311 | + | </instant> | |
| 312 | + | <instant group="attack" spellid="119" name="Rage of the Skies" words="exevo gran mas vis" lvl="55" mana="600" selftarget="1" prem="1" exhaustion="40000" groupcooldown="4000" needlearn="0" script="attack/rage of the skies.lua"> | |
| 313 | + | <vocation name="Sorcerer" /> | |
| 314 | + | <vocation name="Master Sorcerer" /> | |
| 315 | + | </instant> | |
| 316 | + | <instant group="healing" spellid="159" name="Recovery" words="utura" lvl="50" mana="75" aggressive="0" selftarget="1" exhaustion="60000" groupcooldown="1000" needlearn="0" script="healing/recovery.lua"> | |
| 317 | + | <vocation name="Paladin" /> | |
| 318 | + | <vocation name="Knight" /> | |
| 319 | + | <vocation name="Royal Paladin" /> | |
| 320 | + | <vocation name="Elite Knight" /> | |
| 321 | + | </instant> | |
| 322 | + | <instant group="healing" spellid="36" name="Salvation" words="exura gran san" lvl="60" mana="210" prem="1" selftarget="1" aggressive="0" exhaustion="1000" groupcooldown="1000" needlearn="0" script="healing/salvation.lua"> | |
| 323 | + | <vocation name="Paladin" /> | |
| 324 | + | <vocation name="Royal Paladin" /> | |
| 325 | + | </instant> | |
| 326 | + | <instant group="support" spellid="135" name="Sharpshooter" words="utito tempo san" lvl="60" mana="450" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/sharpshooter.lua"> | |
| 327 | + | <vocation name="Paladin" /> | |
| 328 | + | <vocation name="Royal Paladin" /> | |
| 329 | + | </instant> | |
| 330 | + | <instant group="attack" spellid="151" name="Strong Energy Strike" words="exori gran vis" lvl="80" mana="60" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="8000" groupcooldown="2000" needlearn="0" script="attack/strong energy strike.lua"> | |
| 331 | + | <vocation name="Sorcerer" /> | |
| 332 | + | <vocation name="Master Sorcerer" /> | |
| 333 | + | </instant> | |
| 334 | + | <instant group="attack" spellid="57" name="Strong Ethereal Spear" words="exori gran con" lvl="90" mana="55" prem="1" range="7" needtarget="1" exhaustion="8000" groupcooldown="2000" blockwalls="1" needlearn="0" script="attack/strong ethereal spear.lua"> | |
| 335 | + | <vocation name="Paladin" /> | |
| 336 | + | <vocation name="Royal Paladin" /> | |
| 337 | + | </instant> | |
| 338 | + | <instant group="attack" spellid="150" name="Strong Flame Strike" words="exori gran flam" lvl="70" mana="60" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="8000" groupcooldown="2000" needlearn="0" script="attack/strong flame strike.lua"> | |
| 339 | + | <vocation name="Sorcerer" /> | |
| 340 | + | <vocation name="Master Sorcerer" /> | |
| 341 | + | </instant> | |
| 342 | + | <instant group="support" spellid="39" name="Strong Haste" words="utani gran hur" lvl="20" mana="100" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/strong haste.lua"> | |
| 343 | + | <vocation name="Sorcerer" /> | |
| 344 | + | <vocation name="Druid" /> | |
| 345 | + | <vocation name="Master Sorcerer" /> | |
| 346 | + | <vocation name="Elder Druid" /> | |
| 347 | + | </instant> | |
| 348 | + | <instant group="attack" spellid="152" name="Strong Ice Strike" words="exori gran frigo" lvl="80" mana="60" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="8000" groupcooldown="2000" needlearn="0" script="attack/strong ice strike.lua"> | |
| 349 | + | <vocation name="Druid" /> | |
| 350 | + | <vocation name="Elder Druid" /> | |
| 351 | + | </instant> | |
| 352 | + | <instant group="attack" spellid="43" name="Strong Ice Wave" words="exevo gran frigo hur" lvl="40" mana="170" direction="1" exhaustion="8000" groupcooldown="2000" needlearn="0" script="attack/strong ice wave.lua"> | |
| 353 | + | <vocation name="Druid" /> | |
| 354 | + | <vocation name="Elder Druid" /> | |
| 355 | + | </instant> | |
| 356 | + | <instant group="attack" spellid="153" name="Strong Terra Strike" words="exori gran tera" lvl="70" mana="60" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="8000" groupcooldown="2000" needlearn="0" script="attack/strong terra strike.lua"> | |
| 357 | + | <vocation name="Druid" /> | |
| 358 | + | <vocation name="Elder Druid" /> | |
| 359 | + | </instant> | |
| 360 | + | <instant group="support" spellid="9" name="Summon Creature" words="utevo res" lvl="25" params="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="summonMonster"> | |
| 361 | + | <vocation name="Sorcerer" /> | |
| 362 | + | <vocation name="Druid" /> | |
| 363 | + | <vocation name="Master Sorcerer" /> | |
| 364 | + | <vocation name="Elder Druid" /> | |
| 365 | + | </instant> | |
| 366 | + | <instant group="support" spellid="134" name="Swift Foot" words="utamo tempo san" lvl="55" mana="400" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/swift foot.lua"> | |
| 367 | + | <vocation name="Paladin" /> | |
| 368 | + | <vocation name="Royal Paladin" /> | |
| 369 | + | </instant> | |
| 370 | + | <instant group="attack" spellid="113" name="Terra Strike" words="exori tera" lvl="13" mana="20" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="attack/terra strike.lua"> | |
| 371 | + | <vocation name="Sorcerer" /> | |
| 372 | + | <vocation name="Master Sorcerer" /> | |
| 373 | + | <vocation name="Druid" /> | |
| 374 | + | <vocation name="Elder Druid" /> | |
| 375 | + | </instant> | |
| 376 | + | <instant group="attack" spellid="120" name="Terra Wave" words="exevo tera hur" lvl="38" mana="210" direction="1" exhaustion="4000" groupcooldown="2000" needlearn="0" script="attack/terra wave.lua"> | |
| 377 | + | <vocation name="Druid" /> | |
| 378 | + | <vocation name="Elder Druid" /> | |
| 379 | + | </instant> | |
| 380 | + | <instant group="support" spellid="126" name="Train Party" words="utito mas sio" lvl="32" mana="60" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="party/train.lua"> | |
| 381 | + | <vocation name="Knight" /> | |
| 382 | + | <vocation name="Elite Knight" /> | |
| 383 | + | </instant> | |
| 384 | + | <instant group="attack" spellid="155" name="Ultimate Energy Strike" words="exori max vis" lvl="100" mana="100" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="30000" groupcooldown="4000" needlearn="0" script="attack/ultimate energy strike.lua"> | |
| 385 | + | <vocation name="Sorcerer" /> | |
| 386 | + | <vocation name="Master Sorcerer" /> | |
| 387 | + | </instant> | |
| 388 | + | <instant group="attack" spellid="154" name="Ultimate Flame Strike" words="exori max flam" lvl="90" mana="100" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="30000" groupcooldown="4000" needlearn="0" script="attack/ultimate flame strike.lua"> | |
| 389 | + | <vocation name="Sorcerer" /> | |
| 390 | + | <vocation name="Master Sorcerer" /> | |
| 391 | + | </instant> | |
| 392 | + | <instant group="healing" spellid="3" name="Ultimate Healing" words="exura vita" lvl="30" mana="160" aggressive="0" selftarget="1" exhaustion="1000" groupcooldown="1000" needlearn="0" script="healing/ultimate healing.lua"> | |
| 393 | + | <vocation name="Sorcerer" /> | |
| 394 | + | <vocation name="Druid" /> | |
| 395 | + | <vocation name="Master Sorcerer" /> | |
| 396 | + | <vocation name="Elder Druid" /> | |
| 397 | + | </instant> | |
| 398 | + | <instant group="attack" spellid="156" name="Ultimate Ice Strike" words="exori max frigo" lvl="100" mana="100" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="30000" groupcooldown="4000" needlearn="0" script="attack/ultimate ice strike.lua"> | |
| 399 | + | <vocation name="Druid" /> | |
| 400 | + | <vocation name="Elder Druid" /> | |
| 401 | + | </instant> | |
| 402 | + | <instant group="support" spellid="75" name="Ultimate Light" words="utevo vis lux" lvl="26" mana="140" prem="1" aggressive="0" selftarget="1" exhaustion="2000" groupcooldown="2000" needlearn="0" script="support/ultimate light.lua"> | |
| 403 | + | <vocation name="Sorcerer" /> | |
| 404 | + | <vocation name="Druid" /> | |
| 405 | + | <vocation name="Master Sorcerer" /> | |
| 406 | + | <vocation name="Elder Druid" /> | |
| 407 | + | </instant> | |
| 408 | + | <instant group="attack" spellid="157" name="Ultimate Terra Strike" words="exori max tera" lvl="90" mana="100" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1" exhaustion="30000" groupcooldown="4000" needlearn="0" script="attack/ultimate terra strike.lua"> | |
| 409 | + | <vocation name="Druid" /> | |
| 410 | + | <vocation name="Elder Druid" /> | |
| 411 | + | </instant> | |
| 412 | + | <instant group="healing" spellid="123" name="Wound Cleansing" words="exura ico" lvl="10" mana="40" prem="0" selftarget="1" aggressive="0" exhaustion="1000" groupcooldown="1000" needlearn="0" script="healing/wound cleansing.lua"> | |
| 413 | + | <vocation name="Knight" /> | |
| 414 | + | <vocation name="Elite Knight" /> | |
| 415 | + | </instant> | |
| 416 | + | <instant group="attack" spellid="107" name="Whirlwind Throw" words="exori hur" lvl="28" mana="40" prem="1" range="5" needtarget="1" blockwalls="1" needweapon="1" exhaustion="6000" groupcooldown="2000" needlearn="0" script="attack/whirlwind throw.lua"> | |
| 417 | + | <vocation name="Knight" /> | |
| 418 | + | <vocation name="Elite Knight" /> | |
| 419 | + | </instant> | |
| 420 | + | <instant group="attack" spellid="56" name="Wrath of Nature" words="exevo gran mas tera" lvl="55" mana="700" prem="1" selftarget="1" exhaustion="40000" groupcooldown="4000" needlearn="0" script="attack/wrath of nature.lua"> | |
| 421 | + | <vocation name="Druid" /> | |
| 422 | + | <vocation name="Elder Druid" /> | |
| 423 | + | </instant> | |
| 424 | + | ||
| 425 | + | <!-- Attack Runes --> | |
| 426 | + | <rune group="attack" spellid="26" name="Poison Field" id="2285" allowfaruse="1" charges="3" lvl="14" maglv="0" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/poison field.lua" /> | |
| 427 | + | <rune group="attack" spellid="91" name="Poison Bomb" id="2286" allowfaruse="1" charges="2" lvl="25" maglv="4" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/poison bomb.lua" /> | |
| 428 | + | <rune group="attack" spellid="32" name="Poison Wall" id="2289" allowfaruse="1" charges="4" lvl="29" maglv="5" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/poison wall.lua" /> | |
| 429 | + | <rune group="attack" spellid="25" name="Fire Field" id="2301" allowfaruse="1" charges="3" lvl="15" maglv="1" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/fire field.lua" /> | |
| 430 | + | <rune group="attack" spellid="17" name="Firebomb" id="2305" allowfaruse="1" charges="2" lvl="27" maglv="5" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/fire bomb.lua" /> | |
| 431 | + | <rune group="attack" spellid="28" name="Fire Wall" id="2303" allowfaruse="1" charges="4" lvl="33" maglv="6" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/fire wall.lua" /> | |
| 432 | + | <rune group="attack" spellid="50" name="Soulfire" id="2308" allowfaruse="1" charges="3" lvl="27" maglv="7" exhaustion="2000" groupcooldown="2000" needtarget="1" blocktype="solid" script="attack/soul fire.lua" /> | |
| 433 | + | <rune group="attack" spellid="15" name="Fireball" id="2302" allowfaruse="1" charges="5" lvl="27" maglv="4" exhaustion="2000" groupcooldown="2000" needtarget="1" blocktype="solid" script="attack/fireball.lua" /> | |
| 434 | + | <rune group="attack" spellid="16" name="Great Fireball" id="2304" allowfaruse="1" charges="4" lvl="30" maglv="4" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/great fireball.lua" /> | |
| 435 | + | <rune group="attack" spellid="27" name="Energy Field" id="2277" allowfaruse="1" charges="3" lvl="18" maglv="3" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/energy field.lua" /> | |
| 436 | + | <rune group="attack" spellid="55" name="Energybomb" id="2262" allowfaruse="1" charges="2" lvl="37" maglv="10" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/energy bomb.lua" /> | |
| 437 | + | <rune group="attack" spellid="33" name="Energy Wall" id="2279" allowfaruse="1" charges="4" lvl="41" maglv="9" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/energy wall.lua" /> | |
| 438 | + | <rune group="attack" spellid="7" name="Light Magic Missile" id="2287" allowfaruse="1" charges="10" lvl="15" exhaustion="2000" groupcooldown="2000" maglv="0" needtarget="1" blocktype="solid" script="attack/light magic missile.lua" /> | |
| 439 | + | <!--<rune group="attack" spellid="7" name="Lightest Magic Missile" id="2287" allowfaruse="1" charges="10" lvl="1" exhaustion="2000" groupcooldown="2000" maglv="0" needtarget="1" blocktype="solid" script="attack/lightest magic missile.lua" />--> | |
| 440 | + | <rune group="attack" spellid="8" name="Heavy Magic Missile" id="2311" allowfaruse="1" charges="10" lvl="25" exhaustion="2000" groupcooldown="2000" maglv="3" needtarget="1" blocktype="solid" script="attack/heavy magic missile.lua" /> | |
| 441 | + | <rune group="attack" spellid="18" name="Explosion" id="2313" allowfaruse="1" charges="6" lvl="31" maglv="6" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="attack/explosion.lua" /> | |
| 442 | + | <rune group="attack" spellid="21" name="Sudden Death" id="2268" allowfaruse="1" charges="3" lvl="45" maglv="15" exhaustion="2000" groupcooldown="2000" needtarget="1" blocktype="solid" script="attack/sudden death.lua" /> | |
| 443 | + | <rune group="attack" spellid="114" name="Icicle" id="2271" allowfaruse="1" charges="5" lvl="28" maglv="4" exhaustion="2000" groupcooldown="2000" needtarget="1" script="attack/icicle.lua" /> | |
| 444 | + | <rune group="attack" spellid="115" name="Avalanche" id="2274" allowfaruse="1" charges="4" lvl="30" maglv="4" exhaustion="2000" groupcooldown="2000" script="attack/avalanche.lua" /> | |
| 445 | + | <rune group="attack" spellid="116" name="Stone Shower" id="2288" allowfaruse="1" charges="4" lvl="28" maglv="4" exhaustion="2000" groupcooldown="2000" script="attack/stone shower.lua" /> | |
| 446 | + | <rune group="attack" spellid="117" name="Thunderstorm" id="2315" allowfaruse="1" charges="4" lvl="28" maglv="4" exhaustion="2000" groupcooldown="2000" script="attack/thunderstorm.lua" /> | |
| 447 | + | <rune group="attack" spellid="77" name="Stalagmite" id="2292" allowfaruse="1" charges="10" lvl="24" maglv="3" exhaustion="2000" groupcooldown="2000" needtarget="1" script="attack/stalagmite.lua" /> | |
| 448 | + | <rune group="attack" spellid="130" name="Holy Missile" id="2295" allowfaruse="1" charges="5" lvl="27" maglv="4" exhaustion="2000" groupcooldown="2000" needtarget="1" blocktype="solid" script="attack/holy missile.lua"> | |
| 449 | + | <vocation name="Paladin" /> | |
| 450 | + | <vocation name="Royal Paladin" showInDescription="0" /> | |
| 451 | + | </rune> | |
| 452 | + | <rune group="attack" spellid="86" name="Magic Wall" id="2293" allowfaruse="1" charges="3" lvl="32" maglv="9" exhaustion="2000" groupcooldown="2000" blocktype="all" script="support/magic wall rune.lua" /> | |
| 453 | + | ||
| 454 | + | <!-- Healing Runes --> | |
| 455 | + | <rune group="healing" spellid="31" name="Antidote Rune" id="2266" allowfaruse="1" charges="1" lvl="15" maglv="0" exhaustion="2000" groupcooldown="2000" aggressive="0" needtarget="1" blocktype="solid" script="healing/antidote rune.lua" /> | |
| 456 | + | <rune group="healing" spellid="4" name="Intense Healing Rune" id="2265" allowfaruse="1" charges="1" lvl="15" maglv="1" exhaustion="2000" groupcooldown="2000" aggressive="0" needtarget="1" blocktype="solid" script="healing/intense healing rune.lua" /> | |
| 457 | + | <rune group="healing" spellid="5" name="Ultimate Healing Rune" id="2273" allowfaruse="1" charges="1" lvl="24" maglv="4" exhaustion="2000" groupcooldown="2000" aggressive="0" needtarget="1" blocktype="solid" script="healing/ultimate healing rune.lua" /> | |
| 458 | + | ||
| 459 | + | <!-- Summon Runes --> | |
| 460 | + | <rune group="support" spellid="12" name="Convince Creature" id="2290" allowfaruse="1" charges="1" lvl="16" maglv="5" exhaustion="2000" groupcooldown="2000" needtarget="1" blocktype="solid" function="convince" /> | |
| 461 | + | <rune group="support" spellid="83" name="Animate Dead" id="2316" allowfaruse="1" charges="1" lvl="27" maglv="4" exhaustion="2000" groupcooldown="2000" blocktype="solid" script="support/animate dead rune.lua" /> | |
| 462 | + | ||
| 463 | + | <!-- Support Runes --> | |
| 464 | + | <rune group="support" spellid="78" name="Desintegrate" id="2310" allowfaruse="0" charges="3" lvl="21" maglv="4" exhaustion="2000" groupcooldown="2000" range="1" script="support/desintegrate rune.lua" /> | |
| 465 | + | <rune group="support" spellid="30" name="Destroy Field" id="2261" allowfaruse="1" charges="3" lvl="17" maglv="3" exhaustion="2000" groupcooldown="2000" aggressive="0" range="5" script="support/destroy field rune.lua" /> | |
| 466 | + | <rune group="support" spellid="14" name="Chameleon" id="2291" allowfaruse="1" charges="1" lvl="27" maglv="4" exhaustion="2000" groupcooldown="2000" aggressive="0" selftarget="1" blocktype="solid" function="chameleon" /> | |
| 467 | + | <rune group="support" spellid="94" name="Wild Growth" id="2269" allowfaruse="1" charges="2" lvl="27" maglv="8" exhaustion="2000" groupcooldown="2000" blocktype="all" script="support/wild growth rune.lua"> | |
| 468 | + | <vocation name="Druid" /> | |
| 469 | + | <vocation name="Elder Druid" showInDescription="0" /> | |
| 470 | + | </rune> | |
| 471 | + | <rune group="support" spellid="54" name="Paralyze" id="2278" allowfaruse="1" charges="1" lvl="54" maglv="18" exhaustion="2000" groupcooldown="2000" mana="1400" needtarget="1" blocktype="solid" script="support/paralyze rune.lua"> | |
| 472 | + | <vocation name="Druid" /> | |
| 473 | + | <vocation name="Elder Druid" showInDescription="0" /> | |
| 474 | + | </rune> | |
| 475 | + | ||
| 476 | + | <!-- Conjure Spells --> | |
| 477 | + | <conjure group="support" name="Blank Rune" words="adori blank" lvl="20" mana="50" soul="1" conjureId="2260" conjureCount="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 478 | + | <vocation name="Druid" /> | |
| 479 | + | <vocation name="Elder Druid" /> | |
| 480 | + | <vocation name="Paladin" /> | |
| 481 | + | <vocation name="Royal Paladin" /> | |
| 482 | + | <vocation name="Sorcerer" /> | |
| 483 | + | <vocation name="Master Sorcerer" /> | |
| 484 | + | </conjure> | |
| 485 | + | <conjure group="support" spellid="51" name="Conjure Arrow" words="exevo con" lvl="13" mana="100" soul="1" conjureId="2544" conjureCount="10" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureItem"> | |
| 486 | + | <vocation name="Paladin" /> | |
| 487 | + | <vocation name="Royal Paladin" /> | |
| 488 | + | </conjure> | |
| 489 | + | <conjure group="support" spellid="48" name="Conjure Poisoned Arrow" words="exevo con pox" lvl="16" mana="130" soul="2" conjureId="2545" conjureCount="7" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureItem"> | |
| 490 | + | <vocation name="Paladin" /> | |
| 491 | + | <vocation name="Royal Paladin" /> | |
| 492 | + | </conjure> | |
| 493 | + | <conjure group="support" spellid="79" name="Conjure Bolt" words="exevo con mort" lvl="17" mana="140" soul="2" prem="1" conjureId="2543" conjureCount="5" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureItem"> | |
| 494 | + | <vocation name="Paladin" /> | |
| 495 | + | <vocation name="Royal Paladin" /> | |
| 496 | + | </conjure> | |
| 497 | + | <conjure group="support" spellid="108" name="Conjure Sniper Arrow" words="exevo con hur" lvl="24" mana="160" soul="3" prem="1" conjureId="7364" conjureCount="5" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureItem"> | |
| 498 | + | <vocation name="Paladin" /> | |
| 499 | + | <vocation name="Royal Paladin" /> | |
| 500 | + | </conjure> | |
| 501 | + | <conjure group="support" spellid="49" name="Conjure Explosive Arrow" words="exevo con flam" lvl="25" mana="290" soul="3" conjureId="2546" conjureCount="8" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureItem"> | |
| 502 | + | <vocation name="Paladin" /> | |
| 503 | + | <vocation name="Royal Paladin" /> | |
| 504 | + | </conjure> | |
| 505 | + | <conjure group="support" spellid="109" name="Conjure Piercing Bolt" words="exevo con grav" lvl="33" mana="180" soul="3" prem="1" conjureId="7363" conjureCount="5" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureItem"> | |
| 506 | + | <vocation name="Paladin" /> | |
| 507 | + | <vocation name="Royal Paladin" /> | |
| 508 | + | </conjure> | |
| 509 | + | <conjure group="support" spellid="92" name="Enchant Staff" words="exeta vis" lvl="41" mana="80" prem="1" conjureId="2433" reagentId="2401" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureItem"> | |
| 510 | + | <vocation name="Master Sorcerer" /> | |
| 511 | + | </conjure> | |
| 512 | + | <conjure group="support" spellid="110" name="Enchant Spear" words="exeta con" lvl="45" mana="350" soul="3" prem="1" conjureId="7367" reagentId="2389" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureItem"> | |
| 513 | + | <vocation name="Paladin" /> | |
| 514 | + | <vocation name="Royal Paladin" /> | |
| 515 | + | </conjure> | |
| 516 | + | <conjure group="support" spellid="95" name="Conjure Power Bolt" words="exevo con vis" lvl="59" mana="700" soul="4" prem="1" conjureId="2547" conjureCount="10" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureItem"> | |
| 517 | + | <vocation name="Royal Paladin" /> | |
| 518 | + | </conjure> | |
| 519 | + | <conjure name="Poison Field" words="adevo grav pox" lvl="14" mana="200" soul="1" reagentId="2260" conjureId="2285" conjureCount="3" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 520 | + | <vocation name="Sorcerer" /> | |
| 521 | + | <vocation name="Druid" /> | |
| 522 | + | <vocation name="Master Sorcerer" /> | |
| 523 | + | <vocation name="Elder Druid" /> | |
| 524 | + | </conjure> | |
| 525 | + | <conjure name="Light Magic Missile" words="adori min vis" lvl="15" mana="120" soul="1" reagentId="2260" conjureId="2287" conjureCount="10" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 526 | + | <vocation name="Sorcerer" /> | |
| 527 | + | <vocation name="Druid" /> | |
| 528 | + | <vocation name="Master Sorcerer" /> | |
| 529 | + | <vocation name="Elder Druid" /> | |
| 530 | + | </conjure> | |
| 531 | + | <!--<conjure name="Lightest Magic Missile" words="adori dis min vis" lvl="1" mana="5" soul="0" reagentId="2260" conjureId="2287" conjureCount="10" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 532 | + | <vocation name="None" /> | |
| 533 | + | </conjure>--> | |
| 534 | + | <conjure name="Fire Field" words="adevo grav flam" lvl="15" mana="240" soul="1" reagentId="2260" conjureId="2301" conjureCount="3" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 535 | + | <vocation name="Sorcerer" /> | |
| 536 | + | <vocation name="Druid" /> | |
| 537 | + | <vocation name="Master Sorcerer" /> | |
| 538 | + | <vocation name="Elder Druid" /> | |
| 539 | + | </conjure> | |
| 540 | + | <conjure name="Fireball" words="adori flam" lvl="27" mana="460" soul="3" prem="1" reagentId="2260" conjureId="2302" conjureCount="5" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 541 | + | <vocation name="Sorcerer" /> | |
| 542 | + | <vocation name="Master Sorcerer" /> | |
| 543 | + | </conjure> | |
| 544 | + | <conjure name="Energy Field" words="adevo grav vis" lvl="18" mana="320" soul="2" reagentId="2260" conjureId="2277" conjureCount="3" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 545 | + | <vocation name="Sorcerer" /> | |
| 546 | + | <vocation name="Druid" /> | |
| 547 | + | <vocation name="Master Sorcerer" /> | |
| 548 | + | <vocation name="Elder Druid" /> | |
| 549 | + | </conjure> | |
| 550 | + | <conjure name="Stalagmite" words="adori tera" lvl="24" mana="400" soul="2" prem="2" reagentId="2260" conjureId="2292" conjureCount="10" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 551 | + | <vocation name="Sorcerer" /> | |
| 552 | + | <vocation name="Master Sorcerer" /> | |
| 553 | + | <vocation name="Druid" /> | |
| 554 | + | <vocation name="Elder Druid" /> | |
| 555 | + | </conjure> | |
| 556 | + | <conjure name="Great Fireball" words="adori mas flam" lvl="30" mana="530" soul="3" reagentId="2260" conjureId="2304" conjureCount="4" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 557 | + | <vocation name="Sorcerer" /> | |
| 558 | + | <vocation name="Master Sorcerer" /> | |
| 559 | + | </conjure> | |
| 560 | + | <conjure name="Heavy Magic Missile" words="adori vis" lvl="25" mana="350" soul="2" reagentId="2260" conjureId="2311" conjureCount="10" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 561 | + | <vocation name="Sorcerer" /> | |
| 562 | + | <vocation name="Master Sorcerer" /> | |
| 563 | + | <vocation name="Druid" /> | |
| 564 | + | <vocation name="Elder Druid" /> | |
| 565 | + | </conjure> | |
| 566 | + | <conjure name="Poison Bomb" words="adevo mas pox" lvl="25" mana="520" soul="2" prem="1" reagentId="2260" conjureId="2286" conjureCount="2" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 567 | + | <vocation name="Druid" /> | |
| 568 | + | <vocation name="Elder Druid" /> | |
| 569 | + | </conjure> | |
| 570 | + | <conjure name="Firebomb" words="adevo mas flam" lvl="27" mana="600" soul="4" reagentId="2260" conjureId="2305" conjureCount="2" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 571 | + | <vocation name="Sorcerer" /> | |
| 572 | + | <vocation name="Druid" /> | |
| 573 | + | <vocation name="Master Sorcerer" /> | |
| 574 | + | <vocation name="Elder Druid" /> | |
| 575 | + | </conjure> | |
| 576 | + | <conjure name="Soulfire" words="adevo res flam" lvl="27" mana="600" soul="3" prem="1" reagentId="2260" conjureId="2308" conjureCount="3" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 577 | + | <vocation name="Sorcerer" /> | |
| 578 | + | <vocation name="Druid" /> | |
| 579 | + | <vocation name="Master Sorcerer" /> | |
| 580 | + | <vocation name="Elder Druid" /> | |
| 581 | + | </conjure> | |
| 582 | + | <conjure name="Poison Wall" words="adevo mas grav pox" lvl="29" mana="640" soul="3" reagentId="2260" conjureId="2289" conjureCount="4" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 583 | + | <vocation name="Sorcerer" /> | |
| 584 | + | <vocation name="Druid" /> | |
| 585 | + | <vocation name="Master Sorcerer" /> | |
| 586 | + | <vocation name="Elder Druid" /> | |
| 587 | + | </conjure> | |
| 588 | + | <conjure name="Explosion" words="adevo mas hur" lvl="31" mana="570" soul="4" reagentId="2260" conjureId="2313" conjureCount="6" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 589 | + | <vocation name="Sorcerer" /> | |
| 590 | + | <vocation name="Druid" /> | |
| 591 | + | <vocation name="Master Sorcerer" /> | |
| 592 | + | <vocation name="Elder Druid" /> | |
| 593 | + | </conjure> | |
| 594 | + | <conjure name="Fire Wall" words="adevo mas grav flam" lvl="33" mana="780" soul="4" reagentId="2260" conjureId="2303" conjureCount="4" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 595 | + | <vocation name="Sorcerer" /> | |
| 596 | + | <vocation name="Druid" /> | |
| 597 | + | <vocation name="Master Sorcerer" /> | |
| 598 | + | <vocation name="Elder Druid" /> | |
| 599 | + | </conjure> | |
| 600 | + | <conjure name="Energybomb" words="adevo mas vis" lvl="37" mana="880" soul="5" prem="1" reagentId="2260" conjureId="2262" conjureCount="2" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 601 | + | <vocation name="Sorcerer" /> | |
| 602 | + | <vocation name="Master Sorcerer" /> | |
| 603 | + | </conjure> | |
| 604 | + | <conjure name="Energy Wall" words="adevo mas grav vis" lvl="41" mana="1000" soul="5" reagentId="2260" conjureId="2279" conjureCount="4" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 605 | + | <vocation name="Sorcerer" /> | |
| 606 | + | <vocation name="Druid" /> | |
| 607 | + | <vocation name="Master Sorcerer" /> | |
| 608 | + | <vocation name="Elder Druid" /> | |
| 609 | + | </conjure> | |
| 610 | + | <conjure name="Sudden Death" words="adori gran mort" lvl="45" mana="985" soul="5" reagentId="2260" conjureId="2268" conjureCount="3" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 611 | + | <vocation name="Sorcerer" /> | |
| 612 | + | <vocation name="Master Sorcerer" /> | |
| 613 | + | </conjure> | |
| 614 | + | <conjure name="Antidote Rune" words="adana pox" lvl="15" mana="200" soul="1" reagentId="2260" conjureId="2266" conjureCount="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 615 | + | <vocation name="Druid" /> | |
| 616 | + | <vocation name="Elder Druid" /> | |
| 617 | + | </conjure> | |
| 618 | + | <conjure name="Intense Healing Rune" words="adura gran" lvl="15" mana="240" soul="2" reagentId="2260" conjureId="2265" conjureCount="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 619 | + | <vocation name="Druid" /> | |
| 620 | + | <vocation name="Elder Druid" /> | |
| 621 | + | </conjure> | |
| 622 | + | <conjure name="Ultimate Healing Rune" words="adura vita" lvl="24" mana="400" soul="3" reagentId="2260" conjureId="2273" conjureCount="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 623 | + | <vocation name="Druid" /> | |
| 624 | + | <vocation name="Elder Druid" /> | |
| 625 | + | </conjure> | |
| 626 | + | <conjure name="Convince Creature" words="adeta sio" lvl="16" mana="200" soul="3" reagentId="2260" conjureId="2290" conjureCount="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 627 | + | <vocation name="Druid" /> | |
| 628 | + | <vocation name="Elder Druid" /> | |
| 629 | + | </conjure> | |
| 630 | + | <conjure name="Animate Dead" words="adana mort" lvl="27" mana="600" soul="5" prem="1" reagentId="2260" conjureId="2316" conjureCount="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 631 | + | <vocation name="Sorcerer" /> | |
| 632 | + | <vocation name="Druid" /> | |
| 633 | + | <vocation name="Master Sorcerer" /> | |
| 634 | + | <vocation name="Elder Druid" /> | |
| 635 | + | </conjure> | |
| 636 | + | <conjure name="Chameleon" words="adevo ina" lvl="27" mana="600" soul="2" reagentId="2260" conjureId="2291" conjureCount="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 637 | + | <vocation name="Druid" /> | |
| 638 | + | <vocation name="Elder Druid" /> | |
| 639 | + | </conjure> | |
| 640 | + | <conjure name="Destroy Field" words="adito grav" lvl="17" mana="120" soul="2" reagentId="2260" conjureId="2261" conjureCount="3" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 641 | + | <vocation name="Sorcerer" /> | |
| 642 | + | <vocation name="Druid" /> | |
| 643 | + | <vocation name="Paladin" /> | |
| 644 | + | <vocation name="Master Sorcerer" /> | |
| 645 | + | <vocation name="Elder Druid" /> | |
| 646 | + | <vocation name="Royal Paladin" /> | |
| 647 | + | </conjure> | |
| 648 | + | <conjure name="Desintegrate" words="adito tera" lvl="21" mana="200" soul="3" prem="1" reagentId="2260" conjureId="2310" conjureCount="3" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 649 | + | <vocation name="Sorcerer" /> | |
| 650 | + | <vocation name="Druid" /> | |
| 651 | + | <vocation name="Paladin" /> | |
| 652 | + | <vocation name="Master Sorcerer" /> | |
| 653 | + | <vocation name="Elder Druid" /> | |
| 654 | + | <vocation name="Royal Paladin" /> | |
| 655 | + | </conjure> | |
| 656 | + | <conjure name="Magic Wall" words="adevo grav tera" lvl="32" mana="750" soul="5" prem="1" reagentId="2260" conjureId="2293" conjureCount="3" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 657 | + | <vocation name="Sorcerer" /> | |
| 658 | + | <vocation name="Master Sorcerer" /> | |
| 659 | + | </conjure> | |
| 660 | + | <conjure name="Wild Growth" words="adevo grav vita" lvl="27" mana="600" soul="5" prem="1" reagentId="2260" conjureId="2269" conjureCount="2" needlearn="0" function="conjureRune"> | |
| 661 | + | <vocation name="Druid" /> | |
| 662 | + | <vocation name="Elder Druid" /> | |
| 663 | + | </conjure> | |
| 664 | + | <conjure name="Paralyze" words="adana ani" lvl="54" mana="1400" soul="3" prem="1" reagentId="2260" conjureId="2278" conjureCount="1" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 665 | + | <vocation name="Druid" /> | |
| 666 | + | <vocation name="Elder Druid" /> | |
| 667 | + | </conjure> | |
| 668 | + | <conjure name="Icicle" words="adori frigo" lvl="28" mana="460" soul="3" prem="1" reagentId="2260" conjureId="2271" conjureCount="5" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 669 | + | <vocation name="Druid" /> | |
| 670 | + | <vocation name="Elder Druid" /> | |
| 671 | + | </conjure> | |
| 672 | + | <conjure name="Avalanche" words="adori mas frigo" lvl="30" mana="530" soul="3" reagentId="2260" conjureId="2274" conjureCount="4" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 673 | + | <vocation name="Druid" /> | |
| 674 | + | <vocation name="Elder Druid" /> | |
| 675 | + | </conjure> | |
| 676 | + | <conjure name="Stone Shower" words="adori mas tera" lvl="28" mana="430" soul="3" prem="1" reagentId="2260" conjureId="2288" conjureCount="4" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 677 | + | <vocation name="Druid" /> | |
| 678 | + | <vocation name="Elder Druid" /> | |
| 679 | + | </conjure> | |
| 680 | + | <conjure name="Thunderstorm" words="adori mas vis" lvl="28" mana="430" soul="3" prem="1" reagentId="2260" conjureId="2315" conjureCount="4" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 681 | + | <vocation name="Sorcerer" /> | |
| 682 | + | <vocation name="Master Sorcerer" /> | |
| 683 | + | </conjure> | |
| 684 | + | <conjure name="Holy Missile" words="adori san" lvl="27" mana="350" soul="3" prem="1" reagentId="2260" conjureId="2295" conjureCount="5" exhaustion="2000" groupcooldown="2000" needlearn="0" function="conjureRune"> | |
| 685 | + | <vocation name="Paladin" /> | |
| 686 | + | <vocation name="Royal Paladin" /> | |
| 687 | + | </conjure> | |
| 688 | + | ||
| 689 | + | <!-- House Spells --> | |
| 690 | + | <instant spellid="71" name="House Guest List" words="aleta sio" selftarget="1" aggressive="0" function="editHouseGuest" /> | |
| 691 | + | <instant spellid="72" name="House Subowner List" words="aleta som" selftarget="1" aggressive="0" function="editHouseSubOwner" /> | |
| 692 | + | <instant spellid="73" name="House Door List" words="aleta grav" selftarget="1" aggressive="0" function="editHouseDoor" /> | |
| 693 | + | <instant spellid="74" name="House Kick" words="alana sio" params="1" aggressive="0" function="houseKick" /> | |
| 694 | + | ||
| 695 | + | <!-- Monster Spells --> | |
| 696 | + | <instant name="ghastly dragon curse" words="###1" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/ghastly dragon curse.lua" /> | |
| 697 | + | <instant name="djinn electrify" words="###2" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/djinn electrify.lua" /> | |
| 698 | + | <instant name="energy elemental electrify" words="###3" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/energy elemental electrify.lua" /> | |
| 699 | + | <instant name="massive energy elemental electrify" words="###4" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/massive energy elemental electrify.lua" /> | |
| 700 | + | <instant name="massive fire elemental soulfire" words="###5" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/massive fire elemental soulfire.lua" /> | |
| 701 | + | <instant name="hellfire fighter soulfire" words="###6" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/hellfire fighter soulfire.lua" /> | |
| 702 | + | <instant name="hellspawn soulfire" words="###7" aggressive="1" blockwalls="1" range="7" needtarget="1" needlearn="1" script="monster/hellspawn soulfire.lua" /> | |
| 703 | + | <instant name="spectre drown" words="###8" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/spectre drown.lua" /> | |
| 704 | + | <instant name="phantasm drown" words="###9" direction="1" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/phantasm drown.lua" /> | |
| 705 | + | <instant name="undead dragon curse" words="###10" direction="1" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/undead dragon curse.lua" /> | |
| 706 | + | <instant name="draken abomination curse" words="###11" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/draken abomination curse.lua" /> | |
| 707 | + | <instant name="lancer beetle curse" words="###12" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/lancer beetle curse.lua" /> | |
| 708 | + | <instant name="lizard magistratus curse" words="###13" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/lizard magistratus curse.lua" /> | |
| 709 | + | <instant name="death blob curse" words="###14" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/death blob curse.lua" /> | |
| 710 | + | <instant name="choking fear drown" words="###15" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/choking fear drown.lua" /> | |
| 711 | + | <instant name="blightwalker curse" words="###16" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/blightwalker curse.lua" /> | |
| 712 | + | <instant name="sea serpent drown" words="###17" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/sea serpent drown.lua" /> | |
| 713 | + | <instant name="young sea serpent drown" words="###18" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/young sea serpent drown.lua" /> | |
| 714 | + | <instant name="quara constrictor freeze" words="###19" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/quara constrictor freeze.lua" /> | |
| 715 | + | <instant name="quara constrictor electrify" words="###20" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/quara constrictor electrify.lua" /> | |
| 716 | + | <instant name="cliff strider electrify" words="###21" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/cliff strider electrify.lua" /> | |
| 717 | + | <instant name="war golem electrify" words="###22" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/war golem electrify.lua" /> | |
| 718 | + | <instant name="souleater drown" words="###23" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/souleater drown.lua" /> | |
| 719 | + | <instant name="mutated bat curse" words="###24" direction="1" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/mutated bat curse.lua" /> | |
| 720 | + | <instant name="vulcongra soulfire" words="###25" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/vulcongra soulfire.lua" /> | |
| 721 | + | <instant name="lava golem soulfire" words="###26" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/lava golem soulfire.lua" /> | |
| 722 | + | <instant name="magma crawler soulfire" words="###27" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/magma crawler soulfire.lua" /> | |
| 723 | + | <instant name="war golem skill reducer" words="###28" direction="1" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/war golem skill reducer.lua" /> | |
| 724 | + | <instant name="silencer skill reducer" words="###29" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/silencer skill reducer.lua" /> | |
| 725 | + | <instant name="warlock skill reducer" words="###30" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/warlock skill reducer.lua" /> | |
| 726 | + | <instant name="cliff strider skill reducer" words="###31" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/cliff strider skill reducer.lua" /> | |
| 727 | + | <instant name="stampor skill reducer" words="###32" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/stampor skill reducer.lua" /> | |
| 728 | + | <instant name="diabolic imp skill reducer" words="###33" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/diabolic imp skill reducer.lua" /> | |
| 729 | + | <instant name="dark torturer skill reducer" words="###34" direction="1" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/dark torturer skill reducer.lua" /> | |
| 730 | + | <instant name="forest fury skill reducer" words="###35" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/forest fury skill reducer.lua" /> | |
| 731 | + | <instant name="demon outcast skill reducer" words="###36" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/demon outcast skill reducer.lua" /> | |
| 732 | + | <instant name="fury skill reducer" words="###37" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/fury skill reducer.lua" /> | |
| 733 | + | <instant name="barbarian brutetamer skill reducer" words="###38" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/barbarian brutetamer skill reducer.lua" /> | |
| 734 | + | <instant name="deepling spellsinger skill reducer" words="###39" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/deepling spellsinger skill reducer.lua" /> | |
| 735 | + | <instant name="werewolf skill reducer" words="###40" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/werewolf skill reducer.lua" /> | |
| 736 | + | <instant name="ice golem skill reducer" words="###41" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/ice golem skill reducer.lua" /> | |
| 737 | + | <instant name="feversleep skill reducer" words="###42" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/feversleep skill reducer.lua" /> | |
| 738 | + | <instant name="shock head skill reducer 1" words="###43" aggressive="1" blockwalls="1" needtarget="1" needlearn="1" script="monster/shock head skill reducer 1.lua" /> | |
| 739 | + | <instant name="shock head skill reducer 2" words="###44" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/shock head skill reducer 2.lua" /> | |
| 740 | + | <instant name="enslaved dwarf skill reducer 1" words="###45" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/enslaved dwarf skill reducer 1.lua" /> | |
| 741 | + | <instant name="enslaved dwarf skill reducer 2" words="###46" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/enslaved dwarf skill reducer 2.lua" /> | |
| 742 | + | <instant name="djinn cancel invisibility" words="###47" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/djinn cancel invisibility.lua" /> | |
| 743 | + | <instant name="betrayed wraith skill reducer" words="###48" direction="1" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/betrayed wraith skill reducer.lua" /> | |
| 744 | + | <instant name="pirate corsair skill reducer" words="###49" direction="1" aggressive="1" blockwalls="1" needtarget="0" needlearn="1" script="monster/pirate corsair skill reducer.lua" /> | |
| 745 | + | </spells> |
| @@ -0,0 +1,9 @@ | |||
| 1 | + | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | + | <stages> | |
| 3 | + | <config enabled="0" /> | |
| 4 | + | <stage minlevel="1" maxlevel="8" multiplier="7" /> | |
| 5 | + | <stage minlevel="9" maxlevel="20" multiplier="6" /> | |
| 6 | + | <stage minlevel="21" maxlevel="50" multiplier="5" /> | |
| 7 | + | <stage minlevel="51" maxlevel="100" multiplier="4" /> | |
| 8 | + | <stage minlevel="101" multiplier="5" /> | |
| 9 | + | </stages> |
| @@ -0,0 +1,5 @@ | |||
| 1 | + | <?php require_once 'engine/init.php'; theme_open(); | |
| 2 | + | ||
| 3 | + | view('failed'); | |
| 4 | + | ||
| 5 | + | theme_close(); |
| @@ -0,0 +1,16 @@ | |||
| 1 | + | <?php require_once 'engine/init.php'; theme_open(); | |
| 2 | + | ||
| 3 | + | /** | |
| 4 | + | * Public FAQ. | |
| 5 | + | * | |
| 6 | + | * Entries are edited from Admin Panel > Settings > Content > FAQ questions, | |
| 7 | + | * not on this page - this file only reads config('faq.entries'). | |
| 8 | + | */ | |
| 9 | + | ||
| 10 | + | $faqEntries = (array)($config['faq']['entries'] ?? array()); | |
| 11 | + | ||
| 12 | + | view('faq', [ | |
| 13 | + | 'faqEntries' => $faqEntries, | |
| 14 | + | ]); | |
| 15 | + | ||
| 16 | + | theme_close(); |
| @@ -0,0 +1,1148 @@ | |||
| 1 | + | <?php require_once 'engine/init.php'; | |
| 2 | + | znote_csrf_protect_public_post(); | |
| 3 | + | theme_open(); | |
| 4 | + | protect_page(); | |
| 5 | + | error_reporting(E_ALL ^ E_NOTICE); | |
| 6 | + | if (!$config['forum']['enabled']) admin_only($user_data); | |
| 7 | + | znote_forum_style(); | |
| 8 | + | echo '<div class="znx-forum">'; | |
| 9 | + | /* ------------------------------- | |
| 10 | + | --- Znote AAC forum --- | |
| 11 | + | ------------------------------- | |
| 12 | + | Created by Znote. | |
| 13 | + | Version 1.4. | |
| 14 | + | ||
| 15 | + | Changelog (1.0 --> 1.2): | |
| 16 | + | - Updated to the new date/clock time system | |
| 17 | + | - Bootstrap design support. | |
| 18 | + | ||
| 19 | + | Changelog (1.2 --> 1.3): | |
| 20 | + | - Show character outfit as avatar | |
| 21 | + | - Show in-game position | |
| 22 | + | ||
| 23 | + | Changelog (1.3 -> 1.4): | |
| 24 | + | - Fix SQL query error when editing Board name. | |
| 25 | + | */ | |
| 26 | + | // BBCode rendering now lives in engine/function/bbcode.php as znote_bbcode(). | |
| 27 | + | ||
| 28 | + | function znote_forum_editor_assets() { | |
| 29 | + | static $loaded = false; | |
| 30 | + | if ($loaded) return; | |
| 31 | + | $loaded = true; | |
| 32 | + | $v = '3.2.1'; | |
| 33 | + | ?> | |
| 34 | + | <link rel="stylesheet" href="assets/sceditor/themes/defaultdark.min.css?v=<?php echo $v; ?>"> | |
| 35 | + | <link rel="stylesheet" href="assets/sceditor/znote-editor.css?v=<?php echo $v; ?>"> | |
| 36 | + | <script src="assets/sceditor/sceditor.min.js?v=<?php echo $v; ?>"></script> | |
| 37 | + | <script src="assets/sceditor/formats/bbcode.min.js?v=<?php echo $v; ?>"></script> | |
| 38 | + | <script src="assets/sceditor/icons/material.min.js?v=<?php echo $v; ?>"></script> | |
| 39 | + | <script src="assets/sceditor/plugins/undo.min.js?v=<?php echo $v; ?>"></script> | |
| 40 | + | <script src="assets/sceditor/plugins/autoyoutube.min.js?v=<?php echo $v; ?>"></script> | |
| 41 | + | <script src="assets/sceditor/znote-editor.js?v=<?php echo $v; ?>"></script> | |
| 42 | + | <?php | |
| 43 | + | } | |
| 44 | + | ||
| 45 | + | function znote_forum_editor($name, $value = '', $height = 260) { | |
| 46 | + | global $config; | |
| 47 | + | znote_forum_style(); | |
| 48 | + | $max = (int)($config['forum']['maxImagesPerPost'] ?? 1); | |
| 49 | + | ?> | |
| 50 | + | <div class="znote-editor-wrap"> | |
| 51 | + | <textarea class="znote-editor" name="<?php echo $name; ?>" | |
| 52 | + | data-max-images="<?php echo $max; ?>" | |
| 53 | + | data-height="<?php echo (int)$height; ?>" | |
| 54 | + | data-asset-base="assets/sceditor/"><?php echo $value; ?></textarea> | |
| 55 | + | </div> | |
| 56 | + | <p class="znote-editor-note"><?php | |
| 57 | + | echo ($max > 0) | |
| 58 | + | ? 'Up to ' . $max . ' image' . ($max === 1 ? '' : 's') . ' per post.' | |
| 59 | + | : 'Images are not allowed in forum posts.'; | |
| 60 | + | ?></p> | |
| 61 | + | <?php | |
| 62 | + | znote_forum_editor_assets(); | |
| 63 | + | } | |
| 64 | + | ||
| 65 | + | /** | |
| 66 | + | * The "Post as <character>" picker plus the submit button. | |
| 67 | + | * | |
| 68 | + | * This used to be a <select multiple>, which browsers draw as a scrolling list | |
| 69 | + | * box with nothing selected by default - so submitting without first clicking a | |
| 70 | + | * name posted no character id at all and the action silently did nothing. A | |
| 71 | + | * plain dropdown always has a value, and when the account has a single | |
| 72 | + | * character there is nothing to choose, so it is shown as a label instead. | |
| 73 | + | */ | |
| 74 | + | function znote_forum_style() { | |
| 75 | + | static $done = false; | |
| 76 | + | if ($done) return; | |
| 77 | + | $done = true; | |
| 78 | + | echo '<link rel="stylesheet" href="assets/forum.css?v=4.1.0">' . "\n"; | |
| 79 | + | } | |
| 80 | + | ||
| 81 | + | /** Short relative time for the board / thread lists. */ | |
| 82 | + | function znote_forum_ago($ts) { | |
| 83 | + | $ts = (int)$ts; | |
| 84 | + | if ($ts <= 0) return ''; | |
| 85 | + | $d = time() - $ts; | |
| 86 | + | if ($d < 0) $d = 0; | |
| 87 | + | if ($d < 60) return t('forum.ago_now'); | |
| 88 | + | if ($d < 3600) return t('forum.ago_min', array('n' => (int)floor($d / 60))); | |
| 89 | + | if ($d < 86400) return t('forum.ago_hour', array('n' => (int)floor($d / 3600))); | |
| 90 | + | if ($d < 2592000) return t('forum.ago_day', array('n' => (int)floor($d / 86400))); | |
| 91 | + | return date('M j, Y', $ts); | |
| 92 | + | } | |
| 93 | + | function znote_forum_e($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } | |
| 94 | + | ||
| 95 | + | function znote_forum_character_picker(array $chars, string $field, string $submitLabel, string $submitClass = 'btn btn-primary') { | |
| 96 | + | znote_forum_style(); | |
| 97 | + | $only = (count($chars) === 1) ? reset($chars) : null; | |
| 98 | + | ?> | |
| 99 | + | <div class="znote-postas"> | |
| 100 | + | <span class="znote-postas-label"><?= t('forum.post_as') ?></span> | |
| 101 | + | ||
| 102 | + | <?php if ($only !== null): ?> | |
| 103 | + | <input type="hidden" name="<?php echo htmlspecialchars($field, ENT_QUOTES, 'UTF-8'); ?>" value="<?php echo (int)$only['id']; ?>"> | |
| 104 | + | <span class="znote-postas-single"><?php echo htmlspecialchars($only['name'], ENT_QUOTES, 'UTF-8'); ?></span> | |
| 105 | + | <?php else: ?> | |
| 106 | + | <select class="znote-postas-select form-control" name="<?php echo htmlspecialchars($field, ENT_QUOTES, 'UTF-8'); ?>"> | |
| 107 | + | <?php foreach ($chars as $char): ?> | |
| 108 | + | <option value="<?php echo (int)$char['id']; ?>"><?php echo htmlspecialchars($char['name'], ENT_QUOTES, 'UTF-8'); ?></option> | |
| 109 | + | <?php endforeach; ?> | |
| 110 | + | </select> | |
| 111 | + | <?php endif; ?> | |
| 112 | + | ||
| 113 | + | <button type="submit" class="znote-postas-btn <?php echo htmlspecialchars($submitClass, ENT_QUOTES, 'UTF-8'); ?>"> | |
| 114 | + | <?php echo htmlspecialchars($submitLabel, ENT_QUOTES, 'UTF-8'); ?> | |
| 115 | + | </button> | |
| 116 | + | </div> | |
| 117 | + | <?php | |
| 118 | + | } | |
| 119 | + | ||
| 120 | + | Function PlayerHaveAccess($yourChars, $playerName){ | |
| 121 | + | $access = false; | |
| 122 | + | foreach($yourChars as $char) { | |
| 123 | + | if ($char['name'] == $playerName) $access = true; | |
| 124 | + | } | |
| 125 | + | return $access; | |
| 126 | + | } | |
| 127 | + | ||
| 128 | + | // Start page init | |
| 129 | + | $admin = is_admin($user_data); | |
| 130 | + | if ($admin) $yourChars = db()->fetchAll("SELECT `id`, `name`, `group_id` FROM `players` WHERE `level` >= 1 AND `account_id` = ?;", [$user_data['id']]); | |
| 131 | + | else $yourChars = db()->fetchAll("SELECT `id`, `name`, `group_id` FROM `players` WHERE `level` >= ? AND `account_id` = ?;", [(int)$config['forum']['level'], $user_data['id']]); | |
| 132 | + | if (!$yourChars) $yourChars = array(); | |
| 133 | + | $charCount = count($yourChars); | |
| 134 | + | $yourAccess = accountAccess($user_data['id'], znote_server_adapter()->normalizedEngine()); | |
| 135 | + | if ($admin) { | |
| 136 | + | if (!empty($_POST)) { | |
| 137 | + | $guilds = db()->fetchAll("SELECT `id`, `name` FROM `guilds` ORDER BY `name`;"); | |
| 138 | + | $guilds[] = array('id' => '0', 'name' => 'No guild'); | |
| 139 | + | } | |
| 140 | + | $yourAccess = 100; | |
| 141 | + | } | |
| 142 | + | ||
| 143 | + | // Your characters, indexed by char_id | |
| 144 | + | $charData = array(); | |
| 145 | + | foreach ($yourChars as $char) { | |
| 146 | + | $charData[$char['id']] = $char; | |
| 147 | + | if (get_character_guild_rank($char['id']) > 0) { | |
| 148 | + | $guild = get_player_guild_data($char['id']); | |
| 149 | + | $charData[$char['id']]['guild'] = $guild['guild_id']; | |
| 150 | + | $charData[$char['id']]['guild_rank'] = $guild['rank_level']; | |
| 151 | + | } else $charData[$char['id']]['guild'] = '0'; | |
| 152 | + | } | |
| 153 | + | $cooldownw = array( | |
| 154 | + | $user_znote_data['cooldown'], | |
| 155 | + | time(), | |
| 156 | + | $user_znote_data['cooldown'] - time() | |
| 157 | + | ); | |
| 158 | + | ||
| 159 | + | ///////////////// | |
| 160 | + | // Guild Leader & admin | |
| 161 | + | $leader = false; | |
| 162 | + | foreach($charData as $char) { | |
| 163 | + | if ($char['guild'] > 0 && $char['guild_rank'] == 3) $leader = true; | |
| 164 | + | } | |
| 165 | + | if ($admin && !empty($_POST) || $leader && !empty($_POST)) { | |
| 166 | + | $admin_thread_delete = getValue($_POST['admin_thread_delete'] ?? null); | |
| 167 | + | $admin_thread_close = getValue($_POST['admin_thread_close'] ?? null); | |
| 168 | + | $admin_thread_open = getValue($_POST['admin_thread_open'] ?? null); | |
| 169 | + | $admin_thread_sticky = getValue($_POST['admin_thread_sticky'] ?? null); | |
| 170 | + | $admin_thread_unstick = getValue($_POST['admin_thread_unstick'] ?? null); | |
| 171 | + | $admin_thread_id = getValue($_POST['admin_thread_id'] ?? null); | |
| 172 | + | ||
| 173 | + | // delete thread | |
| 174 | + | if ($admin_thread_delete !== false) { | |
| 175 | + | $admin_thread_id = (int)$admin_thread_id; | |
| 176 | + | $access = false; | |
| 177 | + | if (!$admin) { | |
| 178 | + | $thread = db()->fetchOne("SELECT `forum_id` FROM `znote_forum_threads` WHERE `id` = ?;", [$admin_thread_id]); | |
| 179 | + | $forum = db()->fetchOne("SELECT `guild_id` FROM `znote_forum` WHERE `id` = ?;", [$thread['forum_id']]); | |
| 180 | + | foreach($charData as $char) if ($char['guild'] == $forum['guild_id'] && $char['guild_rank'] == 3) $access = true; | |
| 181 | + | } else $access = true; | |
| 182 | + | ||
| 183 | + | if ($access) { | |
| 184 | + | // Delete all associated posts | |
| 185 | + | db()->execute("DELETE FROM `znote_forum_posts` WHERE `thread_id` = ?;", [$admin_thread_id]); | |
| 186 | + | // Delete thread itself | |
| 187 | + | db()->execute("DELETE FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$admin_thread_id]); | |
| 188 | + | acp_log('forum.thread_delete', '#' . $admin_thread_id, ['scope' => $admin ? 'owner' : 'guild_leader']); | |
| 189 | + | echo '<h1>'. t('forum.thread_deleted'). '</h1>'; | |
| 190 | + | } else echo '<p><b><font color="red">'. t('forum.perm_denied'). '</font></b></p>'; | |
| 191 | + | } | |
| 192 | + | ||
| 193 | + | // Close thread | |
| 194 | + | if ($admin_thread_close !== false) { | |
| 195 | + | $admin_thread_id = (int)$admin_thread_id; | |
| 196 | + | $access = false; | |
| 197 | + | if (!$admin) { | |
| 198 | + | $thread = db()->fetchOne("SELECT `forum_id` FROM `znote_forum_threads` WHERE `id` = ?;", [$admin_thread_id]); | |
| 199 | + | $forum = db()->fetchOne("SELECT `guild_id` FROM `znote_forum` WHERE `id` = ?;", [$thread['forum_id']]); | |
| 200 | + | foreach($charData as $char) if ($char['guild'] == $forum['guild_id'] && $char['guild_rank'] == 3) $access = true; | |
| 201 | + | } else $access = true; | |
| 202 | + | if ($access) { | |
| 203 | + | db()->execute("UPDATE `znote_forum_threads` SET `closed` = 1 WHERE `id` = ? LIMIT 1;", [$admin_thread_id]); | |
| 204 | + | acp_log('forum.thread_close', '#' . $admin_thread_id, ['scope' => $admin ? 'owner' : 'guild_leader']); | |
| 205 | + | echo '<h1>'. t('forum.thread_closed'). '</h1>'; | |
| 206 | + | } else echo '<p><b><font color="red">'. t('forum.perm_denied'). '</font></b></p>'; | |
| 207 | + | } | |
| 208 | + | ||
| 209 | + | // open thread | |
| 210 | + | if ($admin_thread_open !== false) { | |
| 211 | + | $admin_thread_id = (int)$admin_thread_id; | |
| 212 | + | $access = false; | |
| 213 | + | if (!$admin) { | |
| 214 | + | $thread = db()->fetchOne("SELECT `forum_id` FROM `znote_forum_threads` WHERE `id` = ?;", [$admin_thread_id]); | |
| 215 | + | $forum = db()->fetchOne("SELECT `guild_id` FROM `znote_forum` WHERE `id` = ?;", [$thread['forum_id']]); | |
| 216 | + | foreach($charData as $char) if ($char['guild'] == $forum['guild_id'] && $char['guild_rank'] == 3) $access = true; | |
| 217 | + | } else $access = true; | |
| 218 | + | if ($access) { | |
| 219 | + | db()->execute("UPDATE `znote_forum_threads` SET `closed` = 0 WHERE `id` = ? LIMIT 1;", [$admin_thread_id]); | |
| 220 | + | acp_log('forum.thread_open', '#' . $admin_thread_id, ['scope' => $admin ? 'owner' : 'guild_leader']); | |
| 221 | + | echo '<h1>'. t('forum.thread_opened'). '</h1>'; | |
| 222 | + | } else echo '<p><b><font color="red">'. t('forum.perm_denied2') .'</font></b></p>'; | |
| 223 | + | } | |
| 224 | + | ||
| 225 | + | // stick thread | |
| 226 | + | if ($admin_thread_sticky !== false) { | |
| 227 | + | $admin_thread_id = (int)$admin_thread_id; | |
| 228 | + | $access = false; | |
| 229 | + | if (!$admin) { | |
| 230 | + | $thread = db()->fetchOne("SELECT `forum_id` FROM `znote_forum_threads` WHERE `id` = ?;", [$admin_thread_id]); | |
| 231 | + | $forum = db()->fetchOne("SELECT `guild_id` FROM `znote_forum` WHERE `id` = ?;", [$thread['forum_id']]); | |
| 232 | + | foreach($charData as $char) if ($char['guild'] == $forum['guild_id'] && $char['guild_rank'] == 3) $access = true; | |
| 233 | + | } else $access = true; | |
| 234 | + | if ($access) { | |
| 235 | + | db()->execute("UPDATE `znote_forum_threads` SET `sticky` = 1 WHERE `id` = ? LIMIT 1;", [$admin_thread_id]); | |
| 236 | + | acp_log('forum.thread_sticky', '#' . $admin_thread_id, ['scope' => $admin ? 'owner' : 'guild_leader']); | |
| 237 | + | echo '<h1>'. t('forum.thread_stuck2'). '</h1>'; | |
| 238 | + | } else echo '<p><b><font color="red">'. t('forum.perm_denied2') .'</font></b></p>'; | |
| 239 | + | } | |
| 240 | + | ||
| 241 | + | // unstick thread | |
| 242 | + | if ($admin_thread_unstick !== false) { | |
| 243 | + | $admin_thread_id = (int)$admin_thread_id; | |
| 244 | + | $access = false; | |
| 245 | + | if (!$admin) { | |
| 246 | + | $thread = db()->fetchOne("SELECT `forum_id` FROM `znote_forum_threads` WHERE `id` = ?;", [$admin_thread_id]); | |
| 247 | + | $forum = db()->fetchOne("SELECT `guild_id` FROM `znote_forum` WHERE `id` = ?;", [$thread['forum_id']]); | |
| 248 | + | foreach($charData as $char) if ($char['guild'] == $forum['guild_id'] && $char['guild_rank'] == 3) $access = true; | |
| 249 | + | } else $access = true; | |
| 250 | + | if ($access) { | |
| 251 | + | db()->execute("UPDATE `znote_forum_threads` SET `sticky` = 0 WHERE `id` = ? LIMIT 1;", [$admin_thread_id]); | |
| 252 | + | acp_log('forum.thread_unsticky', '#' . $admin_thread_id, ['scope' => $admin ? 'owner' : 'guild_leader']); | |
| 253 | + | echo '<h1>'. t('forum.thread_unstuck2'). '</h1>'; | |
| 254 | + | } else echo '<p><b><font color="red">'. t('forum.perm_denied2') .'</font></b></p>'; | |
| 255 | + | } | |
| 256 | + | } | |
| 257 | + | ||
| 258 | + | ///////////////// | |
| 259 | + | // ADMIN FUNCT | |
| 260 | + | if ($admin && !empty($_POST)) { | |
| 261 | + | $admin_post_id = getValue($_POST['admin_post_id'] ?? null); | |
| 262 | + | $admin_post_delete = getValue($_POST['admin_post_delete'] ?? null); | |
| 263 | + | ||
| 264 | + | $admin_category_delete = getValue($_POST['admin_category_delete'] ?? null); | |
| 265 | + | $admin_category_edit = getValue($_POST['admin_category_edit'] ?? null); | |
| 266 | + | $admin_category_id = getValue($_POST['admin_category_id'] ?? null); | |
| 267 | + | ||
| 268 | + | $admin_update_category = getValue($_POST['admin_update_category'] ?? null); | |
| 269 | + | $admin_category_name = getValue($_POST['admin_category_name'] ?? null); | |
| 270 | + | ||
| 271 | + | $admin_category_access = getValue($_POST['admin_category_access'] ?? null); | |
| 272 | + | $admin_category_closed = getValue($_POST['admin_category_closed'] ?? null); | |
| 273 | + | $admin_category_hidden = getValue($_POST['admin_category_hidden'] ?? null); | |
| 274 | + | $admin_category_guild_id = getValue($_POST['admin_category_guild_id'] ?? null); | |
| 275 | + | ||
| 276 | + | if ($admin_category_access === false) $admin_category_access = 0; | |
| 277 | + | if ($admin_category_closed === false) $admin_category_closed = 0; | |
| 278 | + | if ($admin_category_hidden === false) $admin_category_hidden = 0; | |
| 279 | + | if ($admin_category_guild_id === false) $admin_category_guild_id = 0; | |
| 280 | + | ||
| 281 | + | $admin_board_create_name = getValue($_POST['admin_board_create_name'] ?? null); | |
| 282 | + | $admin_board_create_access = getValue($_POST['admin_board_create_access'] ?? null); | |
| 283 | + | $admin_board_create_closed = getValue($_POST['admin_board_create_closed'] ?? null); | |
| 284 | + | $admin_board_create_hidden = getValue($_POST['admin_board_create_hidden'] ?? null); | |
| 285 | + | $admin_board_create_guild_id = getValue($_POST['admin_board_create_guild_id'] ?? null); | |
| 286 | + | ||
| 287 | + | if ($admin_board_create_access === false) $admin_board_create_access = 0; | |
| 288 | + | if ($admin_board_create_closed === false) $admin_board_create_closed = 0; | |
| 289 | + | if ($admin_board_create_hidden === false) $admin_board_create_hidden = 0; | |
| 290 | + | if ($admin_board_create_guild_id === false) $admin_board_create_guild_id = 0; | |
| 291 | + | ||
| 292 | + | // Create board | |
| 293 | + | if ($admin_board_create_name !== false) { | |
| 294 | + | ||
| 295 | + | // Insert data | |
| 296 | + | db()->execute("INSERT INTO `znote_forum` (`name`, `access`, `closed`, `hidden`, `guild_id`) | |
| 297 | + | VALUES (?, ?, ?, ?, ?);", [ | |
| 298 | + | $admin_board_create_name, | |
| 299 | + | $admin_board_create_access, | |
| 300 | + | $admin_board_create_closed, | |
| 301 | + | $admin_board_create_hidden, | |
| 302 | + | $admin_board_create_guild_id, | |
| 303 | + | ]); | |
| 304 | + | acp_log('forum.board_create', (string)$admin_board_create_name, ['access' => $admin_board_create_access, 'guild_id' => $admin_board_create_guild_id]); | |
| 305 | + | echo '<h1>'. t('forum.board_created'). '</h1>'; | |
| 306 | + | } | |
| 307 | + | ||
| 308 | + | ////////////////// | |
| 309 | + | // update category | |
| 310 | + | if ($admin_update_category !== false) { | |
| 311 | + | $admin_category_id = (int)$admin_category_id; | |
| 312 | + | ||
| 313 | + | // Update the category | |
| 314 | + | db()->execute("UPDATE `znote_forum` SET | |
| 315 | + | `name` = ?, | |
| 316 | + | `access` = ?, | |
| 317 | + | `closed` = ?, | |
| 318 | + | `hidden` = ?, | |
| 319 | + | `guild_id` = ? | |
| 320 | + | WHERE `id` = ? LIMIT 1;", [ | |
| 321 | + | $admin_category_name, | |
| 322 | + | $admin_category_access, | |
| 323 | + | $admin_category_closed, | |
| 324 | + | $admin_category_hidden, | |
| 325 | + | $admin_category_guild_id, | |
| 326 | + | $admin_category_id, | |
| 327 | + | ]); | |
| 328 | + | acp_log('forum.board_update', '#' . $admin_category_id, ['access' => $admin_category_access, 'guild_id' => $admin_category_guild_id]); | |
| 329 | + | echo '<h1>'. t('forum.board_updated'). '</h1>'; | |
| 330 | + | } | |
| 331 | + | ||
| 332 | + | ////////////////// | |
| 333 | + | // edit category | |
| 334 | + | if ($admin_category_edit !== false) { | |
| 335 | + | $admin_category_id = (int)$admin_category_id; | |
| 336 | + | $category = db()->fetchOne("SELECT `id`, `name`, `access`, `closed`, `hidden`, `guild_id` | |
| 337 | + | FROM `znote_forum` WHERE `id` = ? LIMIT 1;", [$admin_category_id]); | |
| 338 | + | if ($category !== false) { | |
| 339 | + | ?> | |
| 340 | + | <form action="" method="post"> | |
| 341 | + | <input type="hidden" name="admin_category_id" value="<?php echo $category['id']; ?>"> | |
| 342 | + | <table class="updateTable table table-striped"> | |
| 343 | + | <tr> | |
| 344 | + | <td><label for="admin_category_name"><?= t('forum.board_name') ?></label></td> | |
| 345 | + | <td><input name="admin_category_name" value="<?php echo $category['name']; ?>" class="span12"></td> | |
| 346 | + | ||
| 347 | + | </tr> | |
| 348 | + | <tr> | |
| 349 | + | <td><label for="admin_category_access"><?= t('forum.required_access') ?></label></td> | |
| 350 | + | <td> | |
| 351 | + | <select name="admin_category_access" class="span12"> | |
| 352 | + | <?php | |
| 353 | + | foreach($config['ingame_positions'] as $access => $name) { | |
| 354 | + | if ($access == $category['access']) echo "<option value='$access' selected>$name</option>"; | |
| 355 | + | else echo "<option value='$access'>$name</option>"; | |
| 356 | + | } | |
| 357 | + | ?> | |
| 358 | + | </select> | |
| 359 | + | </td> | |
| 360 | + | </tr> | |
| 361 | + | <tr> | |
| 362 | + | <td><label for="admin_category_closed"><?= t('forum.closed') ?></label></td> | |
| 363 | + | <td> | |
| 364 | + | <select name="admin_category_closed" class="span12"> | |
| 365 | + | <?php | |
| 366 | + | if ($category['closed'] == 1) echo '<option value="1" selected>' . t('common.yes') . '</option>'; | |
| 367 | + | else echo '<option value="1">' . t('common.yes') . '</option>'; | |
| 368 | + | if ($category['closed'] == 0) echo '<option value="0" selected>' . t('common.no') . '</option>'; | |
| 369 | + | else echo '<option value="0">' . t('common.no') . '</option>'; | |
| 370 | + | ?> | |
| 371 | + | </select> | |
| 372 | + | </td> | |
| 373 | + | </tr> | |
| 374 | + | <tr> | |
| 375 | + | <td><label for="admin_category_hidden"><?= t('forum.hidden') ?></label></td> | |
| 376 | + | <td> | |
| 377 | + | <select name="admin_category_hidden" class="span12"> | |
| 378 | + | <?php | |
| 379 | + | if ($category['hidden'] == 1) echo '<option value="1" selected>' . t('common.yes') . '</option>'; | |
| 380 | + | else echo '<option value="1">' . t('common.yes') . '</option>'; | |
| 381 | + | if ($category['hidden'] == 0) echo '<option value="0" selected>' . t('common.no') . '</option>'; | |
| 382 | + | else echo '<option value="0">' . t('common.no') . '</option>'; | |
| 383 | + | ?> | |
| 384 | + | </select> | |
| 385 | + | </td> | |
| 386 | + | </tr> | |
| 387 | + | <tr> | |
| 388 | + | <td><label for="admin_category_guild_id"><?= t('forum.guild_id') ?></label></td> | |
| 389 | + | <td> | |
| 390 | + | <select name="admin_category_guild_id" class="span12"> | |
| 391 | + | <?php foreach($guilds as $guild) { | |
| 392 | + | if ($category['guild_id'] == $guild['id']) echo "<option value='". $guild['id'] ."' selected>". $guild['name'] ."</option>"; | |
| 393 | + | else echo "<option value='". $guild['id'] ."'>". $guild['name'] ."</option>"; | |
| 394 | + | } ?> | |
| 395 | + | </select> | |
| 396 | + | </td> | |
| 397 | + | </tr> | |
| 398 | + | <tr> | |
| 399 | + | <td colspan="2"><input type="submit" name="admin_update_category" value="<?= t('forum.update_board') ?>" style="width: 100%; height: 30px;" class="btn btn-success"></td> | |
| 400 | + | </tr> | |
| 401 | + | </table> | |
| 402 | + | </form> | |
| 403 | + | <?php | |
| 404 | + | } else echo '<h2>'. t('forum.cat_not_found'). '</h2>'; | |
| 405 | + | ||
| 406 | + | } | |
| 407 | + | ||
| 408 | + | // delete category | |
| 409 | + | if ($admin_category_delete !== false) { | |
| 410 | + | $admin_category_id = (int)$admin_category_id; | |
| 411 | + | ||
| 412 | + | // find all threads in category | |
| 413 | + | $threads = db()->fetchAll("SELECT `id` FROM `znote_forum_threads` WHERE `forum_id` = ?;", [$admin_category_id]); | |
| 414 | + | ||
| 415 | + | // Then loop through all threads, and delete all associated posts: | |
| 416 | + | foreach($threads as $thread) { | |
| 417 | + | db()->execute("DELETE FROM `znote_forum_posts` WHERE `thread_id` = ?;", [$thread['id']]); | |
| 418 | + | } | |
| 419 | + | // Then delete all threads | |
| 420 | + | db()->execute("DELETE FROM `znote_forum_threads` WHERE `forum_id` = ?;", [$admin_category_id]); | |
| 421 | + | // Then delete the category | |
| 422 | + | db()->execute("DELETE FROM `znote_forum` WHERE `id` = ? LIMIT 1;", [$admin_category_id]); | |
| 423 | + | acp_log('forum.board_delete', '#' . $admin_category_id); | |
| 424 | + | echo '<h1>' . t('forum.board_and_threads_deleted') . '</h1>'; | |
| 425 | + | } | |
| 426 | + | ||
| 427 | + | // delete post | |
| 428 | + | if ($admin_post_delete !== false) { | |
| 429 | + | $admin_post_id = (int)$admin_post_id; | |
| 430 | + | ||
| 431 | + | // Delete the post | |
| 432 | + | db()->execute("DELETE FROM `znote_forum_posts` WHERE `id` = ? LIMIT 1;", [$admin_post_id]); | |
| 433 | + | acp_log('forum.post_delete', '#' . $admin_post_id); | |
| 434 | + | echo '<h1>'. t('forum.post_deleted'). '</h1>'; | |
| 435 | + | } | |
| 436 | + | } | |
| 437 | + | // End admin function | |
| 438 | + | ||
| 439 | + | // Fetching get values | |
| 440 | + | if (!empty($_GET)) { | |
| 441 | + | $getCat = getValue($_GET['cat'] ?? null); | |
| 442 | + | $getForum = getValue($_GET['forum'] ?? null); | |
| 443 | + | $getThread = getValue($_GET['thread'] ?? null); | |
| 444 | + | ||
| 445 | + | $new_thread_category = getValue($_POST['new_thread_category'] ?? null); | |
| 446 | + | $new_thread_cid = getValue($_POST['new_thread_cid'] ?? null); | |
| 447 | + | ||
| 448 | + | $create_thread_cid = getValue($_POST['create_thread_cid'] ?? null); | |
| 449 | + | $create_thread_title = getValue($_POST['create_thread_title'] ?? null); | |
| 450 | + | $create_thread_text = getValue($_POST['create_thread_text'] ?? null); | |
| 451 | + | $create_thread_category = getValue($_POST['create_thread_category'] ?? null); | |
| 452 | + | ||
| 453 | + | $update_thread_id = getValue($_POST['update_thread_id'] ?? null); | |
| 454 | + | $update_thread_title = getValue($_POST['update_thread_title'] ?? null); | |
| 455 | + | $update_thread_text = getValue($_POST['update_thread_text'] ?? null); | |
| 456 | + | ||
| 457 | + | $edit_thread = getValue($_POST['edit_thread'] ?? null); | |
| 458 | + | $edit_thread_id = getValue($_POST['edit_thread_id'] ?? null); | |
| 459 | + | ||
| 460 | + | $reply_thread = getValue($_POST['reply_thread'] ?? null); | |
| 461 | + | $reply_text = getValue($_POST['reply_text'] ?? null); | |
| 462 | + | $reply_cid = getValue($_POST['reply_cid'] ?? null); | |
| 463 | + | ||
| 464 | + | $edit_post = getValue($_POST['edit_post'] ?? null); | |
| 465 | + | $edit_post_id = getValue($_POST['edit_post_id'] ?? null); | |
| 466 | + | ||
| 467 | + | $update_post_id = getValue($_POST['update_post_id'] ?? null); | |
| 468 | + | $update_post_text = getValue($_POST['update_post_text'] ?? null); | |
| 469 | + | ||
| 470 | + | // Image cap. The editor checks this too, but that check is a convenience - | |
| 471 | + | // this one is the rule, because a POST does not have to come from the editor. | |
| 472 | + | // Blanking the field makes the save branches below skip, since each requires | |
| 473 | + | // its text to be !== false. | |
| 474 | + | $forumImageLimit = (int)($config['forum']['maxImagesPerPost'] ?? 1); | |
| 475 | + | $forumImageDenied = false; | |
| 476 | + | foreach (array('create_thread_text', 'update_thread_text', 'reply_text', 'update_post_text') as $forumField) { | |
| 477 | + | if ($$forumField !== false && znote_bbcode_count_images($$forumField) > $forumImageLimit) { | |
| 478 | + | $forumImageDenied = true; | |
| 479 | + | $$forumField = false; | |
| 480 | + | } | |
| 481 | + | } | |
| 482 | + | if ($forumImageDenied) { | |
| 483 | + | echo '<p><b><font color="red">' | |
| 484 | + | . ($forumImageLimit > 0 | |
| 485 | + | ? 'Too many images: only ' . $forumImageLimit . ' allowed per post. Nothing was saved.' | |
| 486 | + | : 'Images are not allowed in forum posts. Nothing was saved.') | |
| 487 | + | . '</font></b></p>'; | |
| 488 | + | } | |
| 489 | + | ||
| 490 | + | ///////////////////// | |
| 491 | + | // When you are POSTING in an existing thread | |
| 492 | + | if ($reply_thread !== false && $reply_text !== false && $reply_cid !== false) { | |
| 493 | + | $reply_cid = (int)$reply_cid; | |
| 494 | + | ||
| 495 | + | if ($user_znote_data['cooldown'] < time()) { | |
| 496 | + | user_update_znote_account(array('cooldown'=>(time() + $config['forum']['cooldownPost']))); | |
| 497 | + | ||
| 498 | + | $thread = db()->fetchOne("SELECT `closed` FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$reply_thread]); | |
| 499 | + | ||
| 500 | + | if (!is_array($thread) || !isset($charData[$reply_cid])) $access = false; | |
| 501 | + | else if ($thread['closed'] == 1 && $admin === false) $access = false; | |
| 502 | + | else $access = true; | |
| 503 | + | ||
| 504 | + | if ($access) { | |
| 505 | + | db()->execute("INSERT INTO `znote_forum_posts` (`thread_id`, `player_id`, `player_name`, `text`, `created`, `updated`) VALUES (?, ?, ?, ?, ?, ?);", [$reply_thread, $reply_cid, $charData[$reply_cid]['name'], $reply_text, time(), time()]); | |
| 506 | + | if ($config['forum']['newPostsBumpThreads']) db()->execute("UPDATE `znote_forum_threads` SET `updated` = ? WHERE `id` = ?;", [time(), $reply_thread]); | |
| 507 | + | } else echo '<p><b><font color="red">You don\'t have permission to post on this thread. [Thread: Closed]</font></b></p>'; | |
| 508 | + | } else { | |
| 509 | + | ?> | |
| 510 | + | <p class="forumCooldown"><?= t('forum.antispam') ?> <?php echo ($user_znote_data['cooldown'] - time()); ?> seconds before you can create or post.</p> | |
| 511 | + | <?php | |
| 512 | + | } | |
| 513 | + | } | |
| 514 | + | ||
| 515 | + | ///////////////////// | |
| 516 | + | // When you ARE creating new thread | |
| 517 | + | if ($create_thread_cid !== false && $create_thread_title !== false && $create_thread_text !== false && $create_thread_category !== false) { | |
| 518 | + | if ($user_znote_data['cooldown'] < time()) { | |
| 519 | + | user_update_znote_account(array('cooldown'=>(time() + $config['forum']['cooldownCreate']))); | |
| 520 | + | ||
| 521 | + | $category = db()->fetchOne("SELECT `access`, `closed`, `guild_id` FROM `znote_forum` WHERE `id` = ? LIMIT 1;", [$create_thread_category]); | |
| 522 | + | if ($category !== false) { | |
| 523 | + | $access = true; | |
| 524 | + | if (!$admin) { | |
| 525 | + | if ($category['access'] > $yourAccess) $access = false; | |
| 526 | + | if ($category['guild_id'] > 0) { | |
| 527 | + | $status = false; | |
| 528 | + | foreach($charData as $char) { | |
| 529 | + | if ($char['guild'] == $category['guild_id']) $status = true; | |
| 530 | + | } | |
| 531 | + | if (!$status) $access = false; | |
| 532 | + | } | |
| 533 | + | if ($category['closed'] > 0) $access = false; | |
| 534 | + | } | |
| 535 | + | ||
| 536 | + | if ($access) { | |
| 537 | + | db()->execute("INSERT INTO `znote_forum_threads` | |
| 538 | + | (`forum_id`, `player_id`, `player_name`, `title`, `text`, `created`, `updated`, `sticky`, `hidden`, `closed`) | |
| 539 | + | VALUES (?, ?, ?, ?, ?, ?, ?, 0, 0, 0);", [ | |
| 540 | + | $create_thread_category, | |
| 541 | + | $create_thread_cid, | |
| 542 | + | $charData[$create_thread_cid]['name'], | |
| 543 | + | $create_thread_title, | |
| 544 | + | $create_thread_text, | |
| 545 | + | time(), | |
| 546 | + | time(), | |
| 547 | + | ]); | |
| 548 | + | SendGet(array('cat'=>$create_thread_category), 'forum.php'); | |
| 549 | + | } else echo '<p><b><font color="red">'. t('forum.perm_thread'). '</font></b></p>'; | |
| 550 | + | } else echo t('forum.cat_missing'); | |
| 551 | + | } else { | |
| 552 | + | ?> | |
| 553 | + | <p class="forumCooldown"><?= t('forum.antispam') ?> <?php echo ($user_znote_data['cooldown'] - time()); ?> seconds before you can create or post.</p> | |
| 554 | + | <?php | |
| 555 | + | } | |
| 556 | + | } | |
| 557 | + | ||
| 558 | + | ///////////////////// | |
| 559 | + | // When you ARE updating post | |
| 560 | + | if ($update_post_id !== false && $update_post_text !== false) { | |
| 561 | + | // Fetch the post data | |
| 562 | + | $post = db()->fetchOne("SELECT `id`, `player_name`, `text`, `thread_id` FROM `znote_forum_posts` WHERE `id` = ? LIMIT 1;", [$update_post_id]); | |
| 563 | + | if (!is_array($post)) $post = array('id' => 0, 'player_name' => '', 'text' => '', 'thread_id' => 0); | |
| 564 | + | $thread = db()->fetchOne("SELECT `closed` FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$post['thread_id']]); | |
| 565 | + | ||
| 566 | + | // Verify access | |
| 567 | + | $access = PlayerHaveAccess($yourChars, $post['player_name']); | |
| 568 | + | if ($thread !== false && $thread['closed'] == 1 && $admin === false) $access = false; | |
| 569 | + | if ($admin) $access = true; | |
| 570 | + | //if ($thread === false) $access = false; | |
| 571 | + | ||
| 572 | + | if ($access) { | |
| 573 | + | db()->execute("UPDATE `znote_forum_posts` SET `text` = ?, `updated` = ? WHERE `id` = ?;", [$update_post_text, time(), $update_post_id]); | |
| 574 | + | if ($admin) acp_log('forum.post_update', '#' . (int)$update_post_id); | |
| 575 | + | echo '<h1>' . t('forum.post_updated') . '</h1>'; | |
| 576 | + | } else echo "<p class='znf-alert'>" . t('forum.edit_post_denied') . "</p>"; | |
| 577 | + | } | |
| 578 | + | ||
| 579 | + | ///////////////////// | |
| 580 | + | // When you ARE updating thread | |
| 581 | + | if ($update_thread_id !== false && $update_thread_title !== false && $update_thread_text !== false) { | |
| 582 | + | // Fetch the thread data | |
| 583 | + | $thread = db()->fetchOne("SELECT `id`, `player_name`, `title`, `text`, `closed` FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$update_thread_id]); | |
| 584 | + | if (!is_array($thread)) $thread = array('id' => 0, 'player_name' => '', 'title' => '', 'text' => '', 'closed' => 0); | |
| 585 | + | ||
| 586 | + | // Verify access | |
| 587 | + | $access = PlayerHaveAccess($yourChars, $thread['player_name']); | |
| 588 | + | if ($thread['closed'] == 1 && $admin === false) $access = false; | |
| 589 | + | if ($admin) $access = true; | |
| 590 | + | ||
| 591 | + | if ($access) { | |
| 592 | + | db()->execute("UPDATE `znote_forum_threads` SET `title` = ?, `text` = ? WHERE `id` = ?;", [$update_thread_title, $update_thread_text, $update_thread_id]); | |
| 593 | + | if ($admin) acp_log('forum.thread_update', '#' . (int)$update_thread_id, ['title' => (string)$update_thread_title]); | |
| 594 | + | echo '<h1>'. t('forum.thread_updated'). '</h1>'; | |
| 595 | + | } else echo "<p class='znf-alert'>" . t('forum.edit_thread_denied') . "</p>"; | |
| 596 | + | } | |
| 597 | + | ||
| 598 | + | ///////////////////// | |
| 599 | + | // When you want to edit a post | |
| 600 | + | if ($edit_post_id !== false && $edit_post !== false) { | |
| 601 | + | // Fetch the post data | |
| 602 | + | $post = db()->fetchOne("SELECT `id`, `thread_id`, `text`, `player_name` FROM `znote_forum_posts` WHERE `id` = ? LIMIT 1;", [$edit_post_id]); | |
| 603 | + | if (!is_array($post)) $post = array('id' => 0, 'thread_id' => 0, 'text' => '', 'player_name' => ''); | |
| 604 | + | $thread = db()->fetchOne("SELECT `closed` FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$post['thread_id']]); | |
| 605 | + | if (!is_array($thread)) $thread = array('closed' => 0); | |
| 606 | + | // Verify access | |
| 607 | + | $access = PlayerHaveAccess($yourChars, $post['player_name']); | |
| 608 | + | if ($thread['closed'] == 1 && $admin === false) $access = false; | |
| 609 | + | if ($admin) $access = true; | |
| 610 | + | ||
| 611 | + | if ($access) { | |
| 612 | + | ?> | |
| 613 | + | <h1><?= t('forum.edit_post') ?></h1> | |
| 614 | + | <form type="" method="post"> | |
| 615 | + | <input name="update_post_id" type="hidden" value="<?php echo $post['id']; ?>"> | |
| 616 | + | <?php znote_forum_editor('update_post_text', $post['text'], 300); ?> | |
| 617 | + | <input type="submit" value="<?= t('forum.update_post') ?>" class="btn btn-success"> | |
| 618 | + | </form> | |
| 619 | + | <?php | |
| 620 | + | } else echo '<p><b><font color="red">'. t('forum.no_edit_post') .'</font></b></p>'; | |
| 621 | + | } else | |
| 622 | + | ||
| 623 | + | ///////////////////// | |
| 624 | + | // When you want to edit a thread | |
| 625 | + | if ($edit_thread_id !== false && $edit_thread !== false) { | |
| 626 | + | // Fetch the thread data | |
| 627 | + | $thread = db()->fetchOne("SELECT `id`, `title`, `text`, `player_name`, `closed` FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$edit_thread_id]); | |
| 628 | + | ||
| 629 | + | $access = PlayerHaveAccess($yourChars, $thread['player_name']); | |
| 630 | + | if ($thread['closed'] == 1) $access = false; | |
| 631 | + | if ($admin) $access = true; | |
| 632 | + | ||
| 633 | + | if ($access) { | |
| 634 | + | ?> | |
| 635 | + | <h1><?= t('forum.edit_thread') ?></h1> | |
| 636 | + | <form type="" method="post"> | |
| 637 | + | <input name="update_thread_id" type="hidden" value="<?php echo $thread['id']; ?>"> | |
| 638 | + | <input name="update_thread_title" type="text" value="<?php echo $thread['title']; ?>" style="width: 500px;"><br><br> | |
| 639 | + | <?php znote_forum_editor('update_thread_text', $thread['text'], 300); ?> | |
| 640 | + | <input type="submit" value="<?= t('forum.update_thread') ?>" class="btn btn-success"> | |
| 641 | + | </form> | |
| 642 | + | <?php | |
| 643 | + | } else echo '<p><b><font color="red">'. t('forum.edit_denied'). '</font></b></p>'; | |
| 644 | + | } else | |
| 645 | + | ||
| 646 | + | ///////////////////// | |
| 647 | + | // When you want to view a thread | |
| 648 | + | if ($getThread !== false) { | |
| 649 | + | $getThread = (int)$getThread; | |
| 650 | + | $threadData = db()->fetchOne("SELECT `id`, `forum_id`, `player_id`, `player_name`, `title`, `text`, `created`, `updated`, `sticky`, `hidden`, `closed` FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$getThread]); | |
| 651 | + | ||
| 652 | + | if ($threadData !== false) { | |
| 653 | + | ||
| 654 | + | $category = db()->fetchOne("SELECT `hidden`, `access`, `guild_id` FROM `znote_forum` WHERE `id` = ? LIMIT 1;", [$threadData['forum_id']]); | |
| 655 | + | if ($category === false) die("Thread category does not exist."); | |
| 656 | + | ||
| 657 | + | $access = true; | |
| 658 | + | $leader = false; | |
| 659 | + | if ($category['hidden'] == 1 || $category['access'] > 1 || $category['guild_id'] > 0) { | |
| 660 | + | $access = false; | |
| 661 | + | if ($category['hidden'] == 1) $access = PlayerHaveAccess($yourChars, $threadData['player_name']); | |
| 662 | + | if ($category['access'] > 1 && $yourAccess >= $category['access']) $access = true; | |
| 663 | + | foreach($charData as $char) { | |
| 664 | + | if ($category['guild_id'] == $char['guild']) $access = true; | |
| 665 | + | if ($char['guild_rank'] == 3) $leader = true; | |
| 666 | + | } | |
| 667 | + | if ($admin) $access = true; | |
| 668 | + | } | |
| 669 | + | ||
| 670 | + | ||
| 671 | + | if ($access) { | |
| 672 | + | $threadPlayer = ($config['forum']['outfit_avatars'] || $config['forum']['player_position']) ? db()->fetchOne("SELECT `id`, `group_id`, `sex`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `lookaddons` FROM `players` WHERE `id` = ?;", [$threadData['player_id']]) : false; | |
| 673 | + | ?> | |
| 674 | + | <nav class="znf-crumbs"><a href="forum.php"><?= t('forum.title') ?></a> <span>/</span> <a href="?cat=<?php echo $getCat; ?>"><?php echo $getForum; ?></a></nav> | |
| 675 | + | <h1 id="ThreadTitle" class="znf-title"><?php echo "<a href='?forum=". $getForum ."&cat=". $getCat ."&thread=". $threadData['id'] ."'>". $threadData['title'] ."</a>"; ?></h1> | |
| 676 | + | <article class="znf-post is-op"> | |
| 677 | + | <div class="znf-post__side avatar"> | |
| 678 | + | <a class="znf-post__author" href="characterprofile.php?name=<?php echo $threadData['player_name']; ?>"><?php echo $threadData['player_name']; ?></a> | |
| 679 | + | <?php if ($threadPlayer !== false && $config['forum']['outfit_avatars']): ?> | |
| 680 | + | <img class="znf-post__outfit" src="<?php echo $config['show_outfits']['imageServer']; ?>?id=<?php echo $threadPlayer['looktype']; ?>&addons=<?php echo $threadPlayer['lookaddons']; ?>&head=<?php echo $threadPlayer['lookhead']; ?>&body=<?php echo $threadPlayer['lookbody']; ?>&legs=<?php echo $threadPlayer['looklegs']; ?>&feet=<?php echo $threadPlayer['lookfeet']; ?>" alt="img"> | |
| 681 | + | <?php endif; ?> | |
| 682 | + | <?php if ($threadPlayer !== false && $config['forum']['player_position']): ?> | |
| 683 | + | <span class="znf-post__rank"><?php echo group_id_to_name($threadPlayer['group_id']); ?></span> | |
| 684 | + | <?php endif; ?> | |
| 685 | + | </div> | |
| 686 | + | <div class="znf-post__body"> | |
| 687 | + | <div class="znf-post__meta"><span class="znf-tag znf-tag--sticky"><?= t('forum.op_tag') ?></span> <?php echo getClock($threadData['created'], true); ?></div> | |
| 688 | + | <div class="znf-post__text"><?php echo znote_bbcode($threadData['text']); ?></div> | |
| 689 | + | <?php if ($charCount > 0 && ($threadData['closed'] == 0 || $yourAccess > 3)): ?> | |
| 690 | + | <div class="znf-post__actions"> | |
| 691 | + | <button type="button" class="btn btn-info znf-quote-btn" data-author="<?php echo htmlspecialchars($threadData['player_name'], ENT_QUOTES, 'UTF-8'); ?>"><?= t('forum.quote') ?></button> | |
| 692 | + | </div> | |
| 693 | + | <?php endif; ?> | |
| 694 | + | <template class="znf-quote-source"><?php echo htmlspecialchars($threadData['text'], ENT_QUOTES, 'UTF-8'); ?></template> | |
| 695 | + | </div> | |
| 696 | + | </article> | |
| 697 | + | <?php | |
| 698 | + | if ($admin || $leader) { | |
| 699 | + | ?> | |
| 700 | + | <div class="znf-mod"> | |
| 701 | + | <form action="" method="post"> | |
| 702 | + | <input type="hidden" name="admin_thread_id" value="<?php echo $threadData['id']; ?>"> | |
| 703 | + | <input type="submit" name="admin_thread_delete" value="<?= t('forum.delete_thread') ?>" class="btn btn-danger"> | |
| 704 | + | </form> | |
| 705 | + | <?php if ($threadData['closed'] == 0) { ?> | |
| 706 | + | <form action="" method="post"> | |
| 707 | + | <input type="hidden" name="admin_thread_id" value="<?php echo $threadData['id']; ?>"> | |
| 708 | + | <input type="submit" name="admin_thread_close" value="<?= t('forum.close_thread') ?>" class="btn btn-warning"> | |
| 709 | + | </form> | |
| 710 | + | <?php } else { ?> | |
| 711 | + | <form action="" method="post"> | |
| 712 | + | <input type="hidden" name="admin_thread_id" value="<?php echo $threadData['id']; ?>"> | |
| 713 | + | <input type="submit" name="admin_thread_open" value="<?= t('forum.open_thread') ?>" class="btn btn-success"> | |
| 714 | + | </form> | |
| 715 | + | <?php } ?> | |
| 716 | + | <?php if ($threadData['sticky'] == 0) { ?> | |
| 717 | + | <form action="" method="post"> | |
| 718 | + | <input type="hidden" name="admin_thread_id" value="<?php echo $threadData['id']; ?>"> | |
| 719 | + | <input type="submit" name="admin_thread_sticky" value="<?= t('forum.stick') ?>" class="btn btn-info"> | |
| 720 | + | </form> | |
| 721 | + | <?php } else { ?> | |
| 722 | + | <form action="" method="post"> | |
| 723 | + | <input type="hidden" name="admin_thread_id" value="<?php echo $threadData['id']; ?>"> | |
| 724 | + | <input type="submit" name="admin_thread_unstick" value="<?= t('forum.unstick') ?>" class="btn btn-primary"> | |
| 725 | + | </form> | |
| 726 | + | <?php } ?> | |
| 727 | + | <form action="" method="post"> | |
| 728 | + | <input type="hidden" name="edit_thread_id" value="<?php echo $threadData['id']; ?>"> | |
| 729 | + | <input type="submit" name="edit_thread" value="<?= t('forum.edit_thread') ?>" class="btn btn-warning"> | |
| 730 | + | </form> | |
| 731 | + | </div> | |
| 732 | + | <?php | |
| 733 | + | } else { | |
| 734 | + | if ($threadData['closed'] == 0 && PlayerHaveAccess($yourChars, $threadData['player_name'])) { | |
| 735 | + | ?> | |
| 736 | + | <div class="znf-mod"> | |
| 737 | + | <form action="" method="post"> | |
| 738 | + | <input type="hidden" name="edit_thread_id" value="<?php echo $threadData['id']; ?>"> | |
| 739 | + | <input type="submit" name="edit_thread" value="<?= t('forum.edit_thread') ?>" class="btn btn-info"> | |
| 740 | + | </form> | |
| 741 | + | </div> | |
| 742 | + | <?php | |
| 743 | + | } | |
| 744 | + | } | |
| 745 | + | ?> | |
| 746 | + | <?php | |
| 747 | + | // Display replies... (copy table above and edit each post) | |
| 748 | + | $posts = db()->fetchAll("SELECT `id`, `player_id`, `player_name`, `text`, `created`, `updated` FROM `znote_forum_posts` WHERE `thread_id` = ? ORDER BY `created`;", [$threadData['id']]); | |
| 749 | + | if ($posts !== false) { | |
| 750 | + | // Load extra data (like outfit avatars?) | |
| 751 | + | $players = array(); | |
| 752 | + | $extra = false; | |
| 753 | + | if ($config['forum']['outfit_avatars'] || $config['forum']['player_position']) { | |
| 754 | + | $extra = true; | |
| 755 | + | ||
| 756 | + | foreach($posts as $post) | |
| 757 | + | if (!isset($players[$post['player_id']])) | |
| 758 | + | $players[$post['player_id']] = array(); | |
| 759 | + | ||
| 760 | + | $playerIds = array_keys($players); | |
| 761 | + | $playerIdPlaceholders = implode(',', array_fill(0, count($playerIds), '?')); | |
| 762 | + | $sql_players = db()->fetchAll("SELECT `id`, `group_id`, `sex`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `lookaddons` FROM `players` WHERE `id` IN ({$playerIdPlaceholders});", $playerIds); | |
| 763 | + | ||
| 764 | + | foreach ($sql_players as $player) | |
| 765 | + | $players[$player['id']] = $player; | |
| 766 | + | ||
| 767 | + | } | |
| 768 | + | ||
| 769 | + | foreach($posts as $post) { | |
| 770 | + | ?> | |
| 771 | + | <article class="znf-post<?php echo ($post['player_name'] === $threadData['player_name']) ? ' is-op' : ''; ?>"> | |
| 772 | + | <div class="znf-post__side avatar"> | |
| 773 | + | <a class="znf-post__author" href="characterprofile.php?name=<?php echo $post['player_name']; ?>"><?php echo $post['player_name']; ?></a> | |
| 774 | + | <?php if ($extra && $config['forum']['outfit_avatars']): ?> | |
| 775 | + | <img class="znf-post__outfit" src="<?php echo $config['show_outfits']['imageServer']; ?>?id=<?php echo $players[$post['player_id']]['looktype']; ?>&addons=<?php echo $players[$post['player_id']]['lookaddons']; ?>&head=<?php echo $players[$post['player_id']]['lookhead']; ?>&body=<?php echo $players[$post['player_id']]['lookbody']; ?>&legs=<?php echo $players[$post['player_id']]['looklegs']; ?>&feet=<?php echo $players[$post['player_id']]['lookfeet']; ?>" alt="img"> | |
| 776 | + | <?php endif; ?> | |
| 777 | + | <?php if ($extra && $config['forum']['player_position']): ?> | |
| 778 | + | <span class="znf-post__rank"><?php echo group_id_to_name($players[$post['player_id']]['group_id']); ?></span> | |
| 779 | + | <?php endif; ?> | |
| 780 | + | </div> | |
| 781 | + | <div class="znf-post__body"> | |
| 782 | + | <div class="znf-post__meta"><?php echo getClock($post['created'], true); ?></div> | |
| 783 | + | <div class="znf-post__text"><?php echo znote_bbcode($post['text']); ?></div> | |
| 784 | + | <div class="znf-post__actions"> | |
| 785 | + | <?php | |
| 786 | + | if ($charCount > 0 && ($threadData['closed'] == 0 || $yourAccess > 3)) { | |
| 787 | + | ?> | |
| 788 | + | <button type="button" class="btn btn-info znf-quote-btn" data-author="<?php echo htmlspecialchars($post['player_name'], ENT_QUOTES, 'UTF-8'); ?>"><?= t('forum.quote') ?></button> | |
| 789 | + | <?php | |
| 790 | + | } | |
| 791 | + | if (PlayerHaveAccess($yourChars, $post['player_name']) || $admin) { | |
| 792 | + | if ($admin) { | |
| 793 | + | ?> | |
| 794 | + | <form action="" method="post" class="postButton"> | |
| 795 | + | <input type="hidden" name="admin_post_id" value="<?php echo $post['id']; ?>"> | |
| 796 | + | <input type="submit" name="admin_post_delete" value="<?= t('forum.delete_post') ?>" class="btn btn-danger"> | |
| 797 | + | </form> | |
| 798 | + | <?php | |
| 799 | + | } | |
| 800 | + | if ($threadData['closed'] == 0 || $admin) { | |
| 801 | + | ?> | |
| 802 | + | <form action="" method="post" class="postButton"> | |
| 803 | + | <input type="hidden" name="edit_post_id" value="<?php echo $post['id']; ?>"> | |
| 804 | + | <input type="submit" name="edit_post" value="<?= t('forum.edit_post') ?>" class="btn btn-info"> | |
| 805 | + | </form> | |
| 806 | + | <?php | |
| 807 | + | } | |
| 808 | + | } | |
| 809 | + | ?> | |
| 810 | + | </div> | |
| 811 | + | <template class="znf-quote-source"><?php echo htmlspecialchars($post['text'], ENT_QUOTES, 'UTF-8'); ?></template> | |
| 812 | + | </div> | |
| 813 | + | </article> | |
| 814 | + | <?php | |
| 815 | + | } | |
| 816 | + | } | |
| 817 | + | ||
| 818 | + | // Quick Reply | |
| 819 | + | if ($charCount > 0) { | |
| 820 | + | if ($threadData['closed'] == 0 || $yourAccess > 3) { | |
| 821 | + | ?> | |
| 822 | + | <div class="znf-reply"> | |
| 823 | + | <h3 class="znf-reply__title"><?= t('forum.reply_title') ?></h3> | |
| 824 | + | <form action="" method="post"> | |
| 825 | + | <input name="reply_thread" type="hidden" value="<?php echo $threadData['id']; ?>"> | |
| 826 | + | <?php znote_forum_editor('reply_text', '', 200); ?> | |
| 827 | + | <?php znote_forum_character_picker($yourChars, 'reply_cid', t('forum.reply_btn'), 'btn btn-primary'); ?> | |
| 828 | + | </form> | |
| 829 | + | </div> | |
| 830 | + | <?php | |
| 831 | + | } else echo '<p class="znf-note">' . t('forum.thread_closed_note') . '</p>'; | |
| 832 | + | } else { | |
| 833 | + | ?><p class="znf-note"><?= t('forum.level_required', ['level' => (int)$config['forum']['level']]) ?></p><?php | |
| 834 | + | } | |
| 835 | + | } else echo '<p class="znf-alert">' . t('forum.perm_denied3') . '</p>'; | |
| 836 | + | } else { | |
| 837 | + | ?> | |
| 838 | + | <h1><?= t('forum.thread_unavailable') ?></h1> | |
| 839 | + | <p><?= t('forum.thread_unavailable_text') ?></p> | |
| 840 | + | <p> | |
| 841 | + | <?php | |
| 842 | + | if ($_GET['cat'] > 0 && !empty($_GET['forum'])) { | |
| 843 | + | $tmpCat = getValue($_GET['cat'] ?? null); | |
| 844 | + | $tmpCatName = getValue($_GET['forum'] ?? null); | |
| 845 | + | ?> | |
| 846 | + | <br><a href="forum.php?forum=<?php echo $tmpCatName; ?>&cat=<?php echo $tmpCat; ?>"><?= t('forum.go_back_to') ?> <?php echo $tmpCatName; ?></a></p> | |
| 847 | + | <?php | |
| 848 | + | } else { | |
| 849 | + | ?> | |
| 850 | + | <br><a href="forum.php"><?= t('forum.go_back') ?></a></p> | |
| 851 | + | <?php | |
| 852 | + | } | |
| 853 | + | ?> | |
| 854 | + | <?php | |
| 855 | + | } | |
| 856 | + | ||
| 857 | + | } else | |
| 858 | + | ||
| 859 | + | ///////////////////// | |
| 860 | + | // When you want to create a new thread | |
| 861 | + | if ($new_thread_category !== false && $new_thread_cid !== false) { | |
| 862 | + | // Verify we got access to this category | |
| 863 | + | $category = db()->fetchOne("SELECT `access`, `closed`, `guild_id` FROM `znote_forum` WHERE `id` = ? LIMIT 1;", [$new_thread_category]); | |
| 864 | + | if ($category !== false) { | |
| 865 | + | $access = true; | |
| 866 | + | if (!$admin) { | |
| 867 | + | if ($category['access'] > $yourAccess) $access = false; | |
| 868 | + | if ($category['guild_id'] > 0) { | |
| 869 | + | $status = false; | |
| 870 | + | foreach($charData as $char) { | |
| 871 | + | if ($char['guild'] == $category['guild_id']) $status = true; | |
| 872 | + | } | |
| 873 | + | if (!$status) $access = false; | |
| 874 | + | } | |
| 875 | + | if ($category['closed'] > 0) $access = false; | |
| 876 | + | } | |
| 877 | + | ||
| 878 | + | if ($access) { | |
| 879 | + | ?> | |
| 880 | + | <h1><?= t('forum.create_thread_new') ?></h1> | |
| 881 | + | <form type="" method="post" class="znote-newthread"> | |
| 882 | + | <input name="create_thread_cid" type="hidden" value="<?php echo $new_thread_cid; ?>"> | |
| 883 | + | <input name="create_thread_category" type="hidden" value="<?php echo $new_thread_category; ?>"> | |
| 884 | + | ||
| 885 | + | <div class="znote-newthread-head"> | |
| 886 | + | <span class="znote-postas-label"><?= t('forum.post_as') ?></span> | |
| 887 | + | <span class="znote-postas-single"><?php echo htmlspecialchars($charData[$new_thread_cid]['name'], ENT_QUOTES, 'UTF-8'); ?></span> | |
| 888 | + | </div> | |
| 889 | + | ||
| 890 | + | <input class="znote-newthread-title form-control" name="create_thread_title" type="text" placeholder="<?= t('forum.thread_title_placeholder') ?>" maxlength="60" required> | |
| 891 | + | ||
| 892 | + | <?php znote_forum_editor('create_thread_text', '', 300); ?> | |
| 893 | + | ||
| 894 | + | <div class="znote-newthread-actions"> | |
| 895 | + | <button type="submit" class="btn btn-success"><?= t('forum.create_thread') ?></button> | |
| 896 | + | <a class="btn btn-default" href="forum.php?cat=<?php echo (int)$new_thread_category; ?>">Cancel</a> | |
| 897 | + | </div> | |
| 898 | + | </form> | |
| 899 | + | <?php | |
| 900 | + | } else echo '<p><b><font color="red">'. t('forum.perm_thread'). '</font></b></p>'; | |
| 901 | + | } | |
| 902 | + | } else | |
| 903 | + | ||
| 904 | + | ///////////////////// | |
| 905 | + | // When category is specified | |
| 906 | + | if ($getCat !== false) { | |
| 907 | + | $getCat = (int)$getCat; | |
| 908 | + | ||
| 909 | + | // Fetch category rules | |
| 910 | + | $category = db()->fetchOne("SELECT `name`, `access`, `closed`, `hidden`, `guild_id` FROM `znote_forum` WHERE `id` = ? AND `access` <= ? LIMIT 1;", [$getCat, $yourAccess]); | |
| 911 | + | ||
| 912 | + | if ($category !== false && $category['guild_id'] > 0 && !$admin) { | |
| 913 | + | $access = false; | |
| 914 | + | foreach($charData as $char) if ($category['guild_id'] == $char['guild']) $access = true; | |
| 915 | + | if ($access !== true) $category = false; | |
| 916 | + | } | |
| 917 | + | ||
| 918 | + | if ($category !== false) { | |
| 919 | + | $getCatInt = (int)$getCat; | |
| 920 | + | echo '<nav class="znf-crumbs"><a href="forum.php">' . t('forum.boards') . '</a> <span>/</span> ' . znote_forum_e($category['name']) . '</nav>'; | |
| 921 | + | echo '<div class="znf-bhead"><h1 class="znf-h1">' . znote_forum_e($category['name']) . '</h1></div>'; | |
| 922 | + | ||
| 923 | + | $threads = db()->fetchAll( | |
| 924 | + | "SELECT `t`.`id`, `t`.`player_name`, `t`.`title`, `t`.`sticky`, `t`.`closed`, `t`.`created`, `t`.`updated`, " | |
| 925 | + | . "COUNT(`p`.`id`) AS `reply_count`, COALESCE(MAX(`p`.`created`), 0) AS `last_reply_at` " | |
| 926 | + | . "FROM `znote_forum_threads` `t` LEFT JOIN `znote_forum_posts` `p` ON `p`.`thread_id` = `t`.`id` " | |
| 927 | + | . "WHERE `t`.`forum_id` = ? " | |
| 928 | + | . "GROUP BY `t`.`id`, `t`.`player_name`, `t`.`title`, `t`.`sticky`, `t`.`closed`, `t`.`created`, `t`.`updated` " | |
| 929 | + | . "ORDER BY `t`.`sticky` DESC, `t`.`updated` DESC;", | |
| 930 | + | [$getCatInt] | |
| 931 | + | ); | |
| 932 | + | ||
| 933 | + | $lastReplyBy = array(); | |
| 934 | + | $lrRows = db()->fetchAll( | |
| 935 | + | "SELECT `x`.`thread_id`, `x`.`player_name` FROM `znote_forum_posts` `x` JOIN (" | |
| 936 | + | . "SELECT `p2`.`thread_id`, MAX(`p2`.`created`) AS `mc` FROM `znote_forum_posts` `p2` " | |
| 937 | + | . "JOIN `znote_forum_threads` `t2` ON `t2`.`id` = `p2`.`thread_id` WHERE `t2`.`forum_id` = ? " | |
| 938 | + | . "GROUP BY `p2`.`thread_id`) `y` ON `y`.`thread_id` = `x`.`thread_id` AND `y`.`mc` = `x`.`created`;", | |
| 939 | + | [$getCatInt] | |
| 940 | + | ); | |
| 941 | + | foreach ((array)$lrRows as $row) if (!isset($lastReplyBy[$row['thread_id']])) $lastReplyBy[$row['thread_id']] = $row['player_name']; | |
| 942 | + | ||
| 943 | + | $visibleThreads = array(); | |
| 944 | + | foreach ((array)$threads as $thread) { | |
| 945 | + | $access = true; | |
| 946 | + | if ($category['hidden'] == 1) { | |
| 947 | + | $access = PlayerHaveAccess($yourChars, $thread['player_name']); | |
| 948 | + | if ($yourAccess > 3 || $admin) $access = true; | |
| 949 | + | } | |
| 950 | + | if ($access) $visibleThreads[] = $thread; | |
| 951 | + | } | |
| 952 | + | ?> | |
| 953 | + | <div class="znf-threads"> | |
| 954 | + | <?php if (!$visibleThreads): ?> | |
| 955 | + | <p class="znf-empty"><?php echo t('forum.board_empty'); ?></p> | |
| 956 | + | <?php endif; ?> | |
| 957 | + | <?php foreach ($visibleThreads as $thread): | |
| 958 | + | $e = 'znote_forum_e'; | |
| 959 | + | $turl = 'forum.php?forum=' . urlencode($category['name']) . '&cat=' . $getCatInt . '&thread=' . (int)$thread['id']; | |
| 960 | + | $replyBy = $lastReplyBy[$thread['id']] ?? ''; | |
| 961 | + | ?> | |
| 962 | + | <div class="znf-thread<?php echo $thread['sticky'] ? ' is-sticky' : ''; echo $thread['closed'] ? ' is-locked' : ''; ?>" data-href="<?php echo $e($turl); ?>" onclick="if(!event.target.closest('a,button,form,input'))window.location.href=this.dataset.href"> | |
| 963 | + | <span class="znf-thread__ico"><?php echo $thread['sticky'] ? '📌' : ($thread['closed'] ? '🔒' : '💬'); ?></span> | |
| 964 | + | <span class="znf-thread__main"> | |
| 965 | + | <a class="znf-thread__title" href="<?php echo $e($turl); ?>"><?php echo $e($thread['title']); ?></a> | |
| 966 | + | <span class="znf-thread__meta"><?php echo t('forum.started_by', array('name' => $e($thread['player_name']), 'ago' => znote_forum_ago($thread['created']))); ?></span> | |
| 967 | + | </span> | |
| 968 | + | <span class="znf-thread__stats"> | |
| 969 | + | <b><?php echo (int)$thread['reply_count']; ?></b> <?php echo t('forum.replies_word'); ?><br> | |
| 970 | + | <?php echo (int)$thread['last_reply_at'] > 0 | |
| 971 | + | ? t('forum.last_by', array('name' => $e($replyBy), 'ago' => znote_forum_ago($thread['last_reply_at']))) | |
| 972 | + | : t('forum.no_replies'); ?> | |
| 973 | + | </span> | |
| 974 | + | </div> | |
| 975 | + | <?php endforeach; ?> | |
| 976 | + | </div> | |
| 977 | + | <?php | |
| 978 | + | ||
| 979 | + | /////////// | |
| 980 | + | // Create thread button | |
| 981 | + | if ($charCount > 0) { | |
| 982 | + | if ($category['closed'] == 0 || $admin) { | |
| 983 | + | ?> | |
| 984 | + | <div class="znf-newwrap"> | |
| 985 | + | <form action="" method="post"> | |
| 986 | + | <input type="hidden" value="<?php echo $getCat; ?>" name="new_thread_category"> | |
| 987 | + | <?php znote_forum_character_picker($yourChars, 'new_thread_cid', t('forum.create_thread_new'), 'btn btn-primary'); ?> | |
| 988 | + | </form> | |
| 989 | + | </div> | |
| 990 | + | <?php | |
| 991 | + | } else echo '<p class="znf-note">'. t('forum.board_closed'). '</p>'; | |
| 992 | + | } else echo '<p class="znf-note">'. t('forum.level_required_new_thread', ['level' => (int)$config['forum']['level']]) .'</p>'; | |
| 993 | + | } else echo '<p class="znf-alert">'. t('forum.board_access_denied', ['level' => (int)$config['forum']['level']]) .'</p>'; | |
| 994 | + | ||
| 995 | + | } | |
| 996 | + | } else { | |
| 997 | + | ||
| 998 | + | ////////////////////// | |
| 999 | + | // No category specified, show list of available categories | |
| 1000 | + | $boardWhereParams = []; | |
| 1001 | + | if ($admin) { | |
| 1002 | + | $boardWhere = ''; | |
| 1003 | + | } else { | |
| 1004 | + | $boardWhere = " WHERE `f`.`access` <= ?"; | |
| 1005 | + | $boardWhereParams[] = (int)$yourAccess; | |
| 1006 | + | } | |
| 1007 | + | $categories = db()->fetchAll( | |
| 1008 | + | "SELECT `f`.`id`, `f`.`name`, `f`.`access`, `f`.`closed`, `f`.`hidden`, `f`.`guild_id`, " | |
| 1009 | + | . "COUNT(`t`.`id`) AS `thread_count`, COALESCE(MAX(`t`.`updated`), 0) AS `last_time` " | |
| 1010 | + | . "FROM `znote_forum` `f` LEFT JOIN `znote_forum_threads` `t` ON `t`.`forum_id` = `f`.`id`" | |
| 1011 | + | . $boardWhere | |
| 1012 | + | . " GROUP BY `f`.`id`, `f`.`name`, `f`.`access`, `f`.`closed`, `f`.`hidden`, `f`.`guild_id` ORDER BY `f`.`name`;", | |
| 1013 | + | $boardWhereParams | |
| 1014 | + | ); | |
| 1015 | + | ||
| 1016 | + | $lastThreads = array(); | |
| 1017 | + | $ltRows = db()->fetchAll( | |
| 1018 | + | "SELECT `x`.`forum_id`, `x`.`player_name`, `x`.`title`, `x`.`id` FROM `znote_forum_threads` `x` " | |
| 1019 | + | . "JOIN (SELECT `forum_id`, MAX(`updated`) AS `mu` FROM `znote_forum_threads` GROUP BY `forum_id`) `y` " | |
| 1020 | + | . "ON `y`.`forum_id` = `x`.`forum_id` AND `y`.`mu` = `x`.`updated`;" | |
| 1021 | + | ); | |
| 1022 | + | foreach ((array)$ltRows as $row) if (!isset($lastThreads[$row['forum_id']])) $lastThreads[$row['forum_id']] = $row; | |
| 1023 | + | ||
| 1024 | + | $guild = false; | |
| 1025 | + | foreach ($charData as $char) if ($char['guild'] > 0) $guild = true; | |
| 1026 | + | if (!isset($guilds)) { | |
| 1027 | + | $guilds = db()->fetchAll("SELECT `id`, `name` FROM `guilds` ORDER BY `name`;"); | |
| 1028 | + | $guilds[] = array('id' => '0', 'name' => 'No guild'); | |
| 1029 | + | } | |
| 1030 | + | $guildName = array(); | |
| 1031 | + | foreach ((array)$guilds as $g) $guildName[$g['id']] = $g['name']; | |
| 1032 | + | ||
| 1033 | + | $mainBoards = array(); | |
| 1034 | + | $guildboard = array(); | |
| 1035 | + | foreach ((array)$categories as $b) { | |
| 1036 | + | $li = $lastThreads[$b['id']] ?? null; | |
| 1037 | + | $b['last_author'] = $li['player_name'] ?? ''; | |
| 1038 | + | $b['last_title'] = $li['title'] ?? ''; | |
| 1039 | + | if ((int)$b['guild_id'] > 0) { | |
| 1040 | + | $inGuild = $admin; | |
| 1041 | + | foreach ($charData as $char) if ((int)$b['guild_id'] === (int)$char['guild']) $inGuild = true; | |
| 1042 | + | if ($inGuild) $guildboard[] = $b; | |
| 1043 | + | } else { | |
| 1044 | + | $mainBoards[] = $b; | |
| 1045 | + | } | |
| 1046 | + | } | |
| 1047 | + | ||
| 1048 | + | $znfBoardRow = static function (array $b) use ($admin, $guildName) { | |
| 1049 | + | $e = 'znote_forum_e'; | |
| 1050 | + | $id = (int)$b['id']; | |
| 1051 | + | ?> | |
| 1052 | + | <div class="znf-board" data-href="forum.php?cat=<?php echo $id; ?>" onclick="if(!event.target.closest('a,button,form,input'))window.location.href=this.dataset.href"> | |
| 1053 | + | <span class="znf-board__icon"><?php echo (int)$b['guild_id'] > 0 ? '⚔' : '💬'; ?></span> | |
| 1054 | + | <span class="znf-board__main"> | |
| 1055 | + | <span class="znf-board__name"> | |
| 1056 | + | <a href="forum.php?cat=<?php echo $id; ?>"><?php echo $e($b['name']); ?></a> | |
| 1057 | + | <?php if ($b['closed']): ?><span class="znf-tag znf-tag--lock"><?php echo t('forum.locked_tag'); ?></span><?php endif; ?> | |
| 1058 | + | <?php if ($b['hidden']): ?><span class="znf-tag znf-tag--hidden"><?php echo t('forum.hidden_tag'); ?></span><?php endif; ?> | |
| 1059 | + | <?php if ((int)$b['guild_id'] > 0): ?><span class="znf-tag znf-tag--guild"><?php echo $e($guildName[$b['guild_id']] ?? ''); ?></span><?php endif; ?> | |
| 1060 | + | </span> | |
| 1061 | + | <?php if (!empty($b['last_time'])): ?> | |
| 1062 | + | <span class="znf-board__last"><?php echo t('forum.lastpost'); ?> <b><?php echo $e($b['last_title']); ?></b> · <?php echo $e($b['last_author']); ?> · <?php echo znote_forum_ago($b['last_time']); ?></span> | |
| 1063 | + | <?php else: ?> | |
| 1064 | + | <span class="znf-board__last"><?php echo t('forum.board_empty'); ?></span> | |
| 1065 | + | <?php endif; ?> | |
| 1066 | + | </span> | |
| 1067 | + | <span class="znf-board__count"><b><?php echo (int)$b['thread_count']; ?></b> <?php echo t('forum.threads_word'); ?></span> | |
| 1068 | + | <?php if ($admin): ?> | |
| 1069 | + | <span class="znf-board__admin"> | |
| 1070 | + | <form method="post"><input type="hidden" name="admin_category_id" value="<?php echo $id; ?>"><button class="btn btn-warning btn--sm" type="submit" name="admin_category_edit" value="Edit"><?php echo t('forum.edit'); ?></button></form> | |
| 1071 | + | <form method="post"><input type="hidden" name="admin_category_id" value="<?php echo $id; ?>"><button class="btn btn-danger btn--sm" type="submit" name="admin_category_delete" value="1"><?php echo t('forum.delete_btn'); ?></button></form> | |
| 1072 | + | </span> | |
| 1073 | + | <?php endif; ?> | |
| 1074 | + | </div> | |
| 1075 | + | <?php | |
| 1076 | + | }; | |
| 1077 | + | ?> | |
| 1078 | + | ||
| 1079 | + | <?php if (!$mainBoards && !$guildboard): ?> | |
| 1080 | + | <p class="znf-empty"><?php echo t('forum.no_boards'); ?></p> | |
| 1081 | + | <?php endif; ?> | |
| 1082 | + | ||
| 1083 | + | <?php if ($mainBoards): ?> | |
| 1084 | + | <div class="znf-boards"> | |
| 1085 | + | <div class="znf-boards__title"><?php echo t('forum.boards'); ?></div> | |
| 1086 | + | <?php foreach ($mainBoards as $b) $znfBoardRow($b); ?> | |
| 1087 | + | </div> | |
| 1088 | + | <?php endif; ?> | |
| 1089 | + | ||
| 1090 | + | <?php if ($guildboard || ($guild && $admin)): ?> | |
| 1091 | + | <div class="znf-boards"> | |
| 1092 | + | <div class="znf-boards__title"><?php echo t('forum.guild_boards'); ?></div> | |
| 1093 | + | <?php if ($guildboard) { foreach ($guildboard as $b) $znfBoardRow($b); } else { ?> | |
| 1094 | + | <p class="znf-empty"><?php echo t('forum.no_guildboards2'); ?></p> | |
| 1095 | + | <?php } ?> | |
| 1096 | + | </div> | |
| 1097 | + | <?php endif; ?> | |
| 1098 | + | <hr class="bighr"> | |
| 1099 | + | <?php | |
| 1100 | + | if ($admin) { | |
| 1101 | + | ?> | |
| 1102 | + | <form action="" method="post" class="znf-form"> | |
| 1103 | + | <h2 class="znf-form__title"><?= t('forum.create_board') ?></h2> | |
| 1104 | + | <div class="znf-field"> | |
| 1105 | + | <label for="admin_board_create_name"><?= t('forum.board_name') ?></label> | |
| 1106 | + | <input type="text" id="admin_board_create_name" name="admin_board_create_name" placeholder="<?= t('forum.board_name') ?>"> | |
| 1107 | + | </div> | |
| 1108 | + | <div class="znf-field"> | |
| 1109 | + | <label for="admin_board_create_access"><?= t('forum.required_access') ?></label> | |
| 1110 | + | <select id="admin_board_create_access" name="admin_board_create_access"> | |
| 1111 | + | <?php foreach($config['ingame_positions'] as $access => $name) echo "<option value='$access'>$name</option>"; ?> | |
| 1112 | + | </select> | |
| 1113 | + | </div> | |
| 1114 | + | <div class="znf-field"> | |
| 1115 | + | <label for="admin_board_create_closed"><?= t('forum.closed') ?></label> | |
| 1116 | + | <select id="admin_board_create_closed" name="admin_board_create_closed"> | |
| 1117 | + | <option value="0"><?= t('common.no') ?></option> | |
| 1118 | + | <option value="1"><?= t('common.yes') ?></option> | |
| 1119 | + | </select> | |
| 1120 | + | </div> | |
| 1121 | + | <div class="znf-field"> | |
| 1122 | + | <label for="admin_board_create_hidden"><?= t('forum.hidden') ?></label> | |
| 1123 | + | <select id="admin_board_create_hidden" name="admin_board_create_hidden"> | |
| 1124 | + | <option value="0"><?= t('common.no') ?></option> | |
| 1125 | + | <option value="1"><?= t('common.yes') ?></option> | |
| 1126 | + | </select> | |
| 1127 | + | </div> | |
| 1128 | + | <div class="znf-field"> | |
| 1129 | + | <label for="admin_board_create_guild_id"><?= t('forum.guild_boards') ?></label> | |
| 1130 | + | <select id="admin_board_create_guild_id" name="admin_board_create_guild_id"> | |
| 1131 | + | <?php foreach($guilds as $guild) { | |
| 1132 | + | $sel = ($guild['id'] == 0) ? ' selected' : ''; | |
| 1133 | + | echo "<option value='". $guild['id'] ."'$sel>". $guild['name'] ."</option>"; | |
| 1134 | + | } ?> | |
| 1135 | + | </select> | |
| 1136 | + | </div> | |
| 1137 | + | <div class="znf-field znf-field--submit"> | |
| 1138 | + | <input type="submit" value="<?= t('forum.create_board_btn') ?>" class="btn btn-primary"> | |
| 1139 | + | </div> | |
| 1140 | + | </form> | |
| 1141 | + | <?php | |
| 1142 | + | } | |
| 1143 | + | ||
| 1144 | + | } | |
| 1145 | + | ||
| 1146 | + | ||
| 1147 | + | echo '</div>'; | |
| 1148 | + | theme_close(); ?> |
| @@ -0,0 +1,236 @@ | |||
| 1 | + | <?php require_once 'engine/init.php'; theme_open(); protect_page(); | |
| 2 | + | echo '<link rel="stylesheet" href="assets/forum.css?v=4.1.0">' . "\n"; | |
| 3 | + | echo '<div class="znx-forum">'; | |
| 4 | + | ||
| 5 | + | // Search CONFIG | |
| 6 | + | $searchResults = 30; // How many max search results | |
| 7 | + | ||
| 8 | + | /* Below HTML CODE = Plugin you can put anywhere in Znote AAC where you want search. | |
| 9 | + | <h1>'. t('fsearch.title'). '</h1> | |
| 10 | + | <form action="forum_search.php" method="get"> | |
| 11 | + | <select name="type"> | |
| 12 | + | <option value="1">Title</option> | |
| 13 | + | <option value="2">Post</option> | |
| 14 | + | <option value="3">'. t('fsearch.author_threads'). '</option> | |
| 15 | + | <option value="4">'. t('fsearch.author_posts'). '</option> | |
| 16 | + | <option value="5">'. t('fsearch.latest_posts2'). '</option> | |
| 17 | + | <option value="6">'. t('fsearch.latest_threads2'). '</option> | |
| 18 | + | </select> | |
| 19 | + | <input type="text" name="text" placeholder="Search string"> | |
| 20 | + | <input type="submit" value="<?= t('common.search') ?>"> | |
| 21 | + | </form> | |
| 22 | + | */ | |
| 23 | + | function stripBBCode($text_to_search) { | |
| 24 | + | $pattern = '|[[\/\!]*?[^\[\]]*?]|si'; | |
| 25 | + | $replace = ''; | |
| 26 | + | return preg_replace($pattern, $replace, $text_to_search); | |
| 27 | + | } | |
| 28 | + | ||
| 29 | + | //data_dump($_GET, false, "Post data:"); | |
| 30 | + | ||
| 31 | + | // Fetch and sanitize values: | |
| 32 | + | $type = getValue($_GET['type'] ?? null); | |
| 33 | + | if ($type !== false) $type = (int)$type; | |
| 34 | + | $text = getvalue($_GET['text'] ?? null); | |
| 35 | + | ||
| 36 | + | function forum_search_like_clause(string $column, array $words): array { | |
| 37 | + | if (!$words) { | |
| 38 | + | return ['1=1', []]; | |
| 39 | + | } | |
| 40 | + | $parts = []; | |
| 41 | + | $params = []; | |
| 42 | + | foreach ($words as $word) { | |
| 43 | + | $parts[] = "`{$column}` LIKE ?"; | |
| 44 | + | $params[] = '%' . $word . '%'; | |
| 45 | + | } | |
| 46 | + | return [implode(' AND ', $parts), $params]; | |
| 47 | + | } | |
| 48 | + | ||
| 49 | + | $textWords = ($text !== false) ? explode(' ', $text) : []; | |
| 50 | + | [$textTitleSql, $textTitleParams] = forum_search_like_clause('title', $textWords); | |
| 51 | + | [$textPostSql, $textPostParams] = forum_search_like_clause('text', $textWords); | |
| 52 | + | [$textAuthorSql, $textAuthorParams] = forum_search_like_clause('player_name', $textWords); | |
| 53 | + | if ($text !== false) { | |
| 54 | + | $text = $textWords; | |
| 55 | + | } | |
| 56 | + | ||
| 57 | + | ?> | |
| 58 | + | <h1><?= t('fsearch.title') ?></h1> | |
| 59 | + | <form method="" type="get"> | |
| 60 | + | <select name="type"> | |
| 61 | + | <option value="1" <?php if ($type == 1) echo "selected"; ?>><?= t('fsearch.option_title') ?></option> | |
| 62 | + | <option value="2" <?php if ($type == 2) echo "selected"; ?>><?= t('fsearch.option_post') ?></option> | |
| 63 | + | <option value="3" <?php if ($type == 3) echo "selected"; ?>><?= t('fsearch.author_threads') ?></option> | |
| 64 | + | <option value="4" <?php if ($type == 4) echo "selected"; ?>><?= t('fsearch.author_posts') ?></option> | |
| 65 | + | <option value="5" <?php if ($type == 5) echo "selected"; ?>><?= t('fsearch.latest_posts2') ?></option> | |
| 66 | + | <option value="6" <?php if ($type == 6) echo "selected"; ?>><?= t('fsearch.latest_threads2') ?></option> | |
| 67 | + | </select> | |
| 68 | + | <input type="text" name="text" placeholder="<?= t('fsearch.search_placeholder') ?>" value="<?php if ($text !== false) echo implode(' ', $text); ?>"> | |
| 69 | + | <input type="submit" value="<?= t('common.search') ?>"> | |
| 70 | + | </form> | |
| 71 | + | <?php | |
| 72 | + | ||
| 73 | + | if ($type !== false && $text !== false && $type <= 4 || $type > 4 && $type <= 6) { | |
| 74 | + | $forums = db()->fetchAll("SELECT `id` FROM `znote_forum` WHERE `access`='1' AND `guild_id`='0';"); | |
| 75 | + | if (!is_array($forums)) $forums = array(); | |
| 76 | + | $allowedForums = array(); | |
| 77 | + | foreach($forums as $forum) $allowedForums[] = $forum['id']; | |
| 78 | + | ||
| 79 | + | //data_dump($allowedForums, false, "Allowed forums to search"); | |
| 80 | + | // in_array(6, $allowedForums) | |
| 81 | + | ||
| 82 | + | $results = false; | |
| 83 | + | switch ($type) { | |
| 84 | + | case 1: // Search titles | |
| 85 | + | $results = db()->fetchAll("SELECT `id` AS `thread_id`, `forum_id`, `title`, `text`, `player_name` FROM `znote_forum_threads` WHERE {$textTitleSql} ORDER BY `id` DESC LIMIT ?;", [...$textTitleParams, (int)$searchResults]); | |
| 86 | + | if (!is_array($results)) $results = array(); | |
| 87 | + | // Filter out search results in custom access boards. | |
| 88 | + | for ($i = 0; $i < count($results); $i++) | |
| 89 | + | if (!in_array($results[$i]['forum_id'], $allowedForums)) | |
| 90 | + | $results[$i]['forum_id'] = false; | |
| 91 | + | else { | |
| 92 | + | $results[$i]['title'] = stripBBCode($results[$i]['title']); | |
| 93 | + | $results[$i]['text'] = stripBBCode($results[$i]['text']); | |
| 94 | + | } | |
| 95 | + | ||
| 96 | + | //if ($results !== false) data_dump($results, false, "Search results"); | |
| 97 | + | //else echo "<br><b>'. t('fsearch.no_results'). '</b>"; | |
| 98 | + | break; | |
| 99 | + | ||
| 100 | + | case 2: // Search posts | |
| 101 | + | $results = db()->fetchAll("SELECT `thread_id`, `player_name`, `text` FROM `znote_forum_posts` WHERE {$textPostSql} ORDER BY `id` DESC LIMIT ?;", [...$textPostParams, (int)$searchResults]); | |
| 102 | + | if (!is_array($results)) $results = array(); | |
| 103 | + | // Missing ['forum_id'], ['title'], lets get them | |
| 104 | + | for ($i = 0; $i < count($results); $i++) { | |
| 105 | + | // $results[$i]['asd'] | |
| 106 | + | $thread = db()->fetchOne("SELECT `forum_id`, `title` FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$results[$i]['thread_id']]); | |
| 107 | + | if ($thread !== false) { | |
| 108 | + | $results[$i]['forum_id'] = $thread['forum_id']; | |
| 109 | + | $results[$i]['title'] = $thread['title']; | |
| 110 | + | if (!in_array($results[$i]['forum_id'], $allowedForums)) $results[$i]['forum_id'] = false; | |
| 111 | + | else { | |
| 112 | + | $results[$i]['title'] = stripBBCode($results[$i]['title']); | |
| 113 | + | $results[$i]['text'] = stripBBCode($results[$i]['text']); | |
| 114 | + | } | |
| 115 | + | } else $results[$i]['forum_id'] = false; | |
| 116 | + | ||
| 117 | + | } // DONE. :) | |
| 118 | + | //data_dump(false, $results, "DATA"); | |
| 119 | + | break; | |
| 120 | + | ||
| 121 | + | case 3: // Search authors last threads | |
| 122 | + | $results = db()->fetchAll("SELECT `id` AS `thread_id`, `forum_id`, `title`, `text`, `player_name` FROM `znote_forum_threads` WHERE {$textAuthorSql} ORDER BY `id` DESC LIMIT ?;", [...$textAuthorParams, (int)$searchResults]); | |
| 123 | + | if (!is_array($results)) $results = array(); | |
| 124 | + | // Filter out search results in custom access boards. | |
| 125 | + | for ($i = 0; $i < count($results); $i++) | |
| 126 | + | if (!in_array($results[$i]['forum_id'], $allowedForums)) | |
| 127 | + | $results[$i]['forum_id'] = false; | |
| 128 | + | else { | |
| 129 | + | $results[$i]['title'] = stripBBCode($results[$i]['title']); | |
| 130 | + | $results[$i]['text'] = stripBBCode($results[$i]['text']); | |
| 131 | + | } | |
| 132 | + | ||
| 133 | + | //if ($results !== false) data_dump($results, false, "Search results"); | |
| 134 | + | //else echo "<br><b>'. t('fsearch.no_results'). '</b>"; | |
| 135 | + | break; | |
| 136 | + | ||
| 137 | + | case 4: // Search authors last posts | |
| 138 | + | $results = db()->fetchAll("SELECT `thread_id`, `player_name`, `text` FROM `znote_forum_posts` WHERE {$textAuthorSql} ORDER BY `id` DESC LIMIT ?;", [...$textAuthorParams, (int)$searchResults]); | |
| 139 | + | if (!is_array($results)) $results = array(); | |
| 140 | + | // Missing ['forum_id'], ['title'], lets get them | |
| 141 | + | for ($i = 0; $i < count($results); $i++) { | |
| 142 | + | // $results[$i]['asd'] | |
| 143 | + | $thread = db()->fetchOne("SELECT `forum_id`, `title` FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$results[$i]['thread_id']]); | |
| 144 | + | if ($thread !== false) { | |
| 145 | + | $results[$i]['forum_id'] = $thread['forum_id']; | |
| 146 | + | $results[$i]['title'] = $thread['title']; | |
| 147 | + | if (!in_array($results[$i]['forum_id'], $allowedForums)) $results[$i]['forum_id'] = false; | |
| 148 | + | else { | |
| 149 | + | $results[$i]['title'] = stripBBCode($results[$i]['title']); | |
| 150 | + | $results[$i]['text'] = stripBBCode($results[$i]['text']); | |
| 151 | + | } | |
| 152 | + | } else $results[$i]['forum_id'] = false; | |
| 153 | + | ||
| 154 | + | } // DONE. :) | |
| 155 | + | break; | |
| 156 | + | ||
| 157 | + | case 5: // Search latest titles | |
| 158 | + | $results = db()->fetchAll("SELECT `id` AS `thread_id`, `forum_id`, `title`, `text`, `player_name` FROM `znote_forum_threads` ORDER BY `id` DESC LIMIT ?;", [(int)$searchResults]); | |
| 159 | + | if (!is_array($results)) $results = array(); | |
| 160 | + | // Filter out search results in custom access boards. | |
| 161 | + | for ($i = 0; $i < count($results); $i++) | |
| 162 | + | if (!in_array($results[$i]['forum_id'], $allowedForums)) | |
| 163 | + | $results[$i]['forum_id'] = false; | |
| 164 | + | else { | |
| 165 | + | $results[$i]['title'] = stripBBCode($results[$i]['title']); | |
| 166 | + | $results[$i]['text'] = stripBBCode($results[$i]['text']); | |
| 167 | + | } | |
| 168 | + | ||
| 169 | + | //if ($results !== false) data_dump($results, false, "Search results"); | |
| 170 | + | //else echo "<br><b>No results.</b>"; | |
| 171 | + | break; | |
| 172 | + | ||
| 173 | + | case 6: // Search posts | |
| 174 | + | $results = db()->fetchAll("SELECT `thread_id`, `player_name`, `text` FROM `znote_forum_posts` ORDER BY `id` DESC LIMIT ?;", [(int)$searchResults]); | |
| 175 | + | if (!is_array($results)) $results = array(); | |
| 176 | + | // Missing ['forum_id'], ['title'], lets get them | |
| 177 | + | for ($i = 0; $i < count($results); $i++) { | |
| 178 | + | // $results[$i]['asd'] | |
| 179 | + | $thread = db()->fetchOne("SELECT `forum_id`, `title` FROM `znote_forum_threads` WHERE `id` = ? LIMIT 1;", [$results[$i]['thread_id']]); | |
| 180 | + | if ($thread !== false) { | |
| 181 | + | $results[$i]['forum_id'] = $thread['forum_id']; | |
| 182 | + | $results[$i]['title'] = $thread['title']; | |
| 183 | + | if (!in_array($results[$i]['forum_id'], $allowedForums)) $results[$i]['forum_id'] = false; | |
| 184 | + | else { | |
| 185 | + | $results[$i]['title'] = stripBBCode($results[$i]['title']); | |
| 186 | + | $results[$i]['text'] = stripBBCode($results[$i]['text']); | |
| 187 | + | } | |
| 188 | + | } else $results[$i]['forum_id'] = false; | |
| 189 | + | ||
| 190 | + | } // DONE. :) | |
| 191 | + | //data_dump(false, $results, "DATA"); | |
| 192 | + | break; | |
| 193 | + | default: | |
| 194 | + | # code... | |
| 195 | + | break; | |
| 196 | + | } | |
| 197 | + | ||
| 198 | + | // Create table and show stuff! | |
| 199 | + | if ($results !== false) { | |
| 200 | + | $count = 0; | |
| 201 | + | foreach ($results as $r) if ($r['forum_id'] !== false) $count++; | |
| 202 | + | if ($count > 0) { | |
| 203 | + | ?> | |
| 204 | + | <table class="znoteTable" id="forumThreadTable"> | |
| 205 | + | <tr class="yellow"> | |
| 206 | + | <th><?= t('fsearch.col_char') ?></th> | |
| 207 | + | <th><?= t('fsearch.col_thread') ?></th> | |
| 208 | + | <th><?= t('fsearch.col_post') ?></th> | |
| 209 | + | </tr> | |
| 210 | + | <?php | |
| 211 | + | foreach ($results as $result) { | |
| 212 | + | if ($result['forum_id'] !== false) { | |
| 213 | + | // $result required fields = ['thread_id'], ['forum_id'], ['title'], ['text'], ['player_name'] | |
| 214 | + | ?> | |
| 215 | + | <tr> | |
| 216 | + | <td><a href="characterprofile.php?name=<?php echo $result['player_name']; ?>"><?php echo $result['player_name']; ?></a></td> | |
| 217 | + | <td> | |
| 218 | + | <a href="forum.php?thread=<?php echo $result['thread_id']; ?>&forum=Search&cat=<?php echo $result['forum_id']; ?>"> | |
| 219 | + | <?php echo $result['title']; ?> | |
| 220 | + | </a> | |
| 221 | + | </td> | |
| 222 | + | <td><?php echo (strlen($result['text']) > 140) ? substr($result['text'],0,137).'...' : $result['text']; ?></td> | |
| 223 | + | </tr> | |
| 224 | + | <?php | |
| 225 | + | } | |
| 226 | + | } | |
| 227 | + | ?> | |
| 228 | + | </table> | |
| 229 | + | <?php | |
| 230 | + | } else echo t('fsearch.no_results'); | |
| 231 | + | } else echo t('fsearch.no_results'); | |
| 232 | + | } else echo "<br><b>". t('fsearch.fill_all2'). "</b>"; | |
| 233 | + | ||
| 234 | + | echo '</div>'; | |
| 235 | + | theme_close(); | |
| 236 | + | ?> |
| @@ -0,0 +1,16 @@ | |||
| 1 | + | <?php require_once 'engine/init.php'; | |
| 2 | + | znote_csrf_protect_public_post(); | |
| 3 | + | theme_open(); | |
| 4 | + | ||
| 5 | + | /* SETUP INSTALLATION | |
| 6 | + | - See comments above $config['gallery'] in config.php */ | |
| 7 | + | ||
| 8 | + | $logged_in = user_logged_in(); | |
| 9 | + | ||
| 10 | + | // Public gallery images, prepared here so the view only renders them. | |
| 11 | + | $galleryCache = new Cache('engine/cache/gallery'); | |
| 12 | + | $images = $galleryCache->load(); | |
| 13 | + | ||
| 14 | + | view('gallery'); | |
| 15 | + | ||
| 16 | + | theme_close(); |