summaryrefslogtreecommitdiff
path: root/npc
diff options
context:
space:
mode:
authorSaulc <lucashelaine14@gmail.com>2018-01-13 20:50:42 +0100
committerSaulc <lucashelaine14@gmail.com>2018-01-13 20:50:42 +0100
commit20df2abc1aca00d6aa5dc78347133890f36b32f3 (patch)
tree4ad4a8bb8b0605473a702e314799a4626347721a /npc
downloadserverdata-20df2abc1aca00d6aa5dc78347133890f36b32f3.tar.gz
serverdata-20df2abc1aca00d6aa5dc78347133890f36b32f3.tar.bz2
serverdata-20df2abc1aca00d6aa5dc78347133890f36b32f3.tar.xz
serverdata-20df2abc1aca00d6aa5dc78347133890f36b32f3.zip
Initial commit
Diffstat (limited to 'npc')
-rw-r--r--npc/000-0-0/import.txt5
-rw-r--r--npc/000-0-0/mapflags.txt1
-rw-r--r--npc/000-0-0/qonan.txt15
-rw-r--r--npc/000-0-0/sailors.txt85
-rw-r--r--npc/000-0-1/_import.txt4
-rw-r--r--npc/000-0-1/mapflags.txt1
-rw-r--r--npc/000-0-1/narrator.txt37
-rw-r--r--npc/000-0/_import.txt4
-rw-r--r--npc/000-0/mapflags.txt1
-rw-r--r--npc/000-0/sailors.txt80
-rw-r--r--npc/000-1/_import.txt23
-rw-r--r--npc/000-1/_mobs.txt39
-rw-r--r--npc/000-1/_warps.txt3
-rw-r--r--npc/000-1/ale.txt110
-rw-r--r--npc/000-1/astapolos.txt166
-rw-r--r--npc/000-1/chest.txt65
-rw-r--r--npc/000-1/couwan.txt95
-rw-r--r--npc/000-1/darlin.txt149
-rw-r--r--npc/000-1/fexil.txt44
-rw-r--r--npc/000-1/gugli.txt249
-rw-r--r--npc/000-1/gulukan.txt170
-rw-r--r--npc/000-1/jalad.txt131
-rw-r--r--npc/000-1/lean.txt74
-rw-r--r--npc/000-1/mapflags.txt1
-rw-r--r--npc/000-1/maxe.txt112
-rw-r--r--npc/000-1/muller.txt132
-rw-r--r--npc/000-1/panels.txt54
-rw-r--r--npc/000-1/sapartan.txt102
-rw-r--r--npc/000-1/shop.txt33
-rw-r--r--npc/000-1/silvio.txt186
-rw-r--r--npc/000-1/tarlan.txt65
-rw-r--r--npc/000-1/tibbo.txt124
-rw-r--r--npc/000-2-0/_import.txt9
-rw-r--r--npc/000-2-0/_mobs.txt4
-rw-r--r--npc/000-2-0/_warps.txt3
-rw-r--r--npc/000-2-0/billybons.txt96
-rw-r--r--npc/000-2-0/doors.txt85
-rw-r--r--npc/000-2-0/julia.txt302
-rw-r--r--npc/000-2-0/mapflags.txt1
-rw-r--r--npc/000-2-0/note.txt27
-rw-r--r--npc/000-2-1/_import.txt17
-rw-r--r--npc/000-2-1/_mobs.txt4
-rw-r--r--npc/000-2-1/_savepoints.txt38
-rw-r--r--npc/000-2-1/_warps.txt3
-rw-r--r--npc/000-2-1/alige.txt320
-rw-r--r--npc/000-2-1/arpan.txt272
-rw-r--r--npc/000-2-1/chefgado.txt213
-rw-r--r--npc/000-2-1/chest.txt72
-rw-r--r--npc/000-2-1/dan.txt94
-rw-r--r--npc/000-2-1/devis.txt17
-rw-r--r--npc/000-2-1/hammock.txt125
-rw-r--r--npc/000-2-1/knife.txt47
-rw-r--r--npc/000-2-1/mapflags.txt1
-rw-r--r--npc/000-2-1/peter.txt339
-rw-r--r--npc/000-2-1/q'onan.txt16
-rw-r--r--npc/000-2-1/story_save.txt30
-rw-r--r--npc/000-2-2/_import.txt5
-rw-r--r--npc/000-2-2/doors.txt69
-rw-r--r--npc/000-2-2/mapflags.txt1
-rw-r--r--npc/000-2-2/ratto.txt68
-rw-r--r--npc/000-2-3/_import.txt10
-rw-r--r--npc/000-2-3/_warps.txt3
-rw-r--r--npc/000-2-3/box.txt112
-rw-r--r--npc/000-2-3/elmo.txt67
-rw-r--r--npc/000-2-3/hammock.txt17
-rw-r--r--npc/000-2-3/mapflags.txt1
-rw-r--r--npc/000-2-3/nard.txt277
-rw-r--r--npc/000-2-3/piourocket.txt29
-rw-r--r--npc/000-2-3/sailors.txt47
-rw-r--r--npc/000-2-4/_import.txt6
-rw-r--r--npc/000-2-4/_mobs.txt3
-rw-r--r--npc/000-2-4/_warps.txt3
-rw-r--r--npc/000-2-4/alige.txt39
-rw-r--r--npc/000-2-4/mapflags.txt1
-rw-r--r--npc/001-1/_import.txt42
-rw-r--r--npc/001-1/_mobs.txt32
-rw-r--r--npc/001-1/_warps.txt445
-rw-r--r--npc/001-1/apana.txt76
-rw-r--r--npc/001-1/artaxe.txt19
-rw-r--r--npc/001-1/beuss.txt28
-rw-r--r--npc/001-1/calypsan.txt105
-rw-r--r--npc/001-1/carmie.txt68
-rw-r--r--npc/001-1/chelios.txt117
-rw-r--r--npc/001-1/cookiemaster.txt258
-rw-r--r--npc/001-1/devis.txt100
-rw-r--r--npc/001-1/doors.txt57
-rw-r--r--npc/001-1/elmo.txt20
-rw-r--r--npc/001-1/enora.txt455
-rw-r--r--npc/001-1/eugene.txt84
-rw-r--r--npc/001-1/fexil.txt144
-rw-r--r--npc/001-1/flyingpiou.txt161
-rw-r--r--npc/001-1/harbours.txt84
-rw-r--r--npc/001-1/hinnack.txt76
-rw-r--r--npc/001-1/juscare.txt93
-rw-r--r--npc/001-1/karim.txt117
-rw-r--r--npc/001-1/katja.txt129
-rw-r--r--npc/001-1/lucas.txt19
-rw-r--r--npc/001-1/manhole.txt56
-rw-r--r--npc/001-1/mapflags.txt1
-rw-r--r--npc/001-1/merlin.txt25
-rw-r--r--npc/001-1/mouboo.txt65
-rw-r--r--npc/001-1/nalkri.txt59
-rw-r--r--npc/001-1/panels.txt57
-rw-r--r--npc/001-1/pious.txt16
-rw-r--r--npc/001-1/qonan.txt111
-rw-r--r--npc/001-1/qpid.txt170
-rw-r--r--npc/001-1/rumly.txt226
-rw-r--r--npc/001-1/salem.txt220
-rw-r--r--npc/001-1/shop.txt318
-rw-r--r--npc/001-1/sign.txt186
-rw-r--r--npc/001-1/taree.txt21
-rw-r--r--npc/001-1/treeleaf.txt22
-rw-r--r--npc/001-1/trees.txt235
-rw-r--r--npc/001-1/wateranimation.txt33
-rw-r--r--npc/001-1/xilaxa.txt67
-rw-r--r--npc/001-2-0/_import.txt6
-rw-r--r--npc/001-2-0/_warps.txt4
-rw-r--r--npc/001-2-0/mapflags.txt1
-rw-r--r--npc/001-2-0/resa.txt80
-rw-r--r--npc/001-2-0/shop.txt35
-rw-r--r--npc/001-2-1/_import.txt5
-rw-r--r--npc/001-2-1/_savepoints.txt11
-rw-r--r--npc/001-2-1/_warps.txt3
-rw-r--r--npc/001-2-1/mapflags.txt1
-rw-r--r--npc/001-2-10/_import.txt5
-rw-r--r--npc/001-2-10/_savepoints.txt11
-rw-r--r--npc/001-2-10/_warps.txt4
-rw-r--r--npc/001-2-10/mapflags.txt1
-rw-r--r--npc/001-2-11/_import.txt6
-rw-r--r--npc/001-2-11/_savepoints.txt11
-rw-r--r--npc/001-2-11/_warps.txt3
-rw-r--r--npc/001-2-11/mapflags.txt1
-rw-r--r--npc/001-2-11/mona.txt67
-rw-r--r--npc/001-2-12/_import.txt5
-rw-r--r--npc/001-2-12/_warps.txt5
-rw-r--r--npc/001-2-12/mapflags.txt1
-rw-r--r--npc/001-2-12/oscar.txt145
-rw-r--r--npc/001-2-13/_import.txt5
-rw-r--r--npc/001-2-13/_savepoints.txt11
-rw-r--r--npc/001-2-13/_warps.txt3
-rw-r--r--npc/001-2-13/mapflags.txt1
-rw-r--r--npc/001-2-14/_import.txt4
-rw-r--r--npc/001-2-14/_warps.txt3
-rw-r--r--npc/001-2-14/mapflags.txt1
-rw-r--r--npc/001-2-15/_import.txt5
-rw-r--r--npc/001-2-15/_savepoints.txt11
-rw-r--r--npc/001-2-15/_warps.txt3
-rw-r--r--npc/001-2-15/mapflags.txt1
-rw-r--r--npc/001-2-16/_import.txt4
-rw-r--r--npc/001-2-16/_warps.txt4
-rw-r--r--npc/001-2-16/mapflags.txt1
-rw-r--r--npc/001-2-17/_import.txt4
-rw-r--r--npc/001-2-17/_warps.txt3
-rw-r--r--npc/001-2-17/mapflags.txt1
-rw-r--r--npc/001-2-18/_import.txt4
-rw-r--r--npc/001-2-18/_warps.txt4
-rw-r--r--npc/001-2-18/mapflags.txt1
-rw-r--r--npc/001-2-19/_import.txt5
-rw-r--r--npc/001-2-19/_warps.txt51
-rw-r--r--npc/001-2-19/lloyd.txt244
-rw-r--r--npc/001-2-19/mapflags.txt1
-rw-r--r--npc/001-2-2/_import.txt5
-rw-r--r--npc/001-2-2/_warps.txt4
-rw-r--r--npc/001-2-2/mapflags.txt1
-rw-r--r--npc/001-2-2/moon.txt214
-rw-r--r--npc/001-2-20/_import.txt4
-rw-r--r--npc/001-2-20/_warps.txt26
-rw-r--r--npc/001-2-20/mapflags.txt1
-rw-r--r--npc/001-2-21/_import.txt6
-rw-r--r--npc/001-2-21/_warps.txt5
-rw-r--r--npc/001-2-21/julia.txt141
-rw-r--r--npc/001-2-21/mapflags.txt1
-rw-r--r--npc/001-2-21/note.txt27
-rw-r--r--npc/001-2-22/_import.txt13
-rw-r--r--npc/001-2-22/_mobs.txt3
-rw-r--r--npc/001-2-22/_savepoints.txt47
-rw-r--r--npc/001-2-22/_warps.txt3
-rw-r--r--npc/001-2-22/alige.txt324
-rw-r--r--npc/001-2-22/chefgado.txt22
-rw-r--r--npc/001-2-22/chest.txt49
-rw-r--r--npc/001-2-22/hammock.txt137
-rw-r--r--npc/001-2-22/knife.txt47
-rw-r--r--npc/001-2-22/mapflags.txt1
-rw-r--r--npc/001-2-22/note.txt33
-rw-r--r--npc/001-2-22/peter.txt335
-rw-r--r--npc/001-2-23/_import.txt6
-rw-r--r--npc/001-2-23/_warps.txt3
-rw-r--r--npc/001-2-23/doors.txt69
-rw-r--r--npc/001-2-23/mapflags.txt1
-rw-r--r--npc/001-2-23/ratto.txt68
-rw-r--r--npc/001-2-24/_import.txt7
-rw-r--r--npc/001-2-24/_warps.txt3
-rw-r--r--npc/001-2-24/hammock.txt17
-rw-r--r--npc/001-2-24/mapflags.txt1
-rw-r--r--npc/001-2-24/nard.txt94
-rw-r--r--npc/001-2-24/piourocket.txt9
-rw-r--r--npc/001-2-25/_import.txt5
-rw-r--r--npc/001-2-25/_mobs.txt3
-rw-r--r--npc/001-2-25/_warps.txt3
-rw-r--r--npc/001-2-25/mapflags.txt1
-rw-r--r--npc/001-2-26/_import.txt6
-rw-r--r--npc/001-2-26/_warps.txt3
-rw-r--r--npc/001-2-26/flask.txt21
-rw-r--r--npc/001-2-26/ivan.txt86
-rw-r--r--npc/001-2-26/mapflags.txt1
-rw-r--r--npc/001-2-27/_import.txt8
-rw-r--r--npc/001-2-27/_warps.txt3
-rw-r--r--npc/001-2-27/don.txt98
-rw-r--r--npc/001-2-27/kaylo.txt44
-rw-r--r--npc/001-2-27/lydon.txt37
-rw-r--r--npc/001-2-27/mapflags.txt1
-rw-r--r--npc/001-2-27/shop.txt60
-rw-r--r--npc/001-2-28/_import.txt8
-rw-r--r--npc/001-2-28/_warps.txt5
-rw-r--r--npc/001-2-28/jenna.txt79
-rw-r--r--npc/001-2-28/mapflags.txt1
-rw-r--r--npc/001-2-28/note.txt25
-rw-r--r--npc/001-2-28/plush.txt130
-rw-r--r--npc/001-2-28/shop.txt25
-rw-r--r--npc/001-2-29/_import.txt5
-rw-r--r--npc/001-2-29/_warps.txt4
-rw-r--r--npc/001-2-29/mapflags.txt1
-rw-r--r--npc/001-2-29/savepoint.txt53
-rw-r--r--npc/001-2-3/_import.txt5
-rw-r--r--npc/001-2-3/_savepoints.txt11
-rw-r--r--npc/001-2-3/_warps.txt3
-rw-r--r--npc/001-2-3/mapflags.txt1
-rw-r--r--npc/001-2-30/_import.txt5
-rw-r--r--npc/001-2-30/_mobs.txt3
-rw-r--r--npc/001-2-30/_warps.txt3
-rw-r--r--npc/001-2-30/mapflags.txt1
-rw-r--r--npc/001-2-31/_import.txt4
-rw-r--r--npc/001-2-31/_warps.txt4
-rw-r--r--npc/001-2-31/mapflags.txt1
-rw-r--r--npc/001-2-32/_import.txt6
-rw-r--r--npc/001-2-32/_warps.txt3
-rw-r--r--npc/001-2-32/doors.txt23
-rw-r--r--npc/001-2-32/mapflags.txt1
-rw-r--r--npc/001-2-32/serena.txt60
-rw-r--r--npc/001-2-33/_import.txt6
-rw-r--r--npc/001-2-33/_warps.txt53
-rw-r--r--npc/001-2-33/lozerk.txt188
-rw-r--r--npc/001-2-33/mapflags.txt2
-rw-r--r--npc/001-2-33/triggers.txt101
-rw-r--r--npc/001-2-34/_import.txt6
-rw-r--r--npc/001-2-34/_warps.txt3
-rw-r--r--npc/001-2-34/doors.txt29
-rw-r--r--npc/001-2-34/mapflags.txt1
-rw-r--r--npc/001-2-34/samantha.txt21
-rw-r--r--npc/001-2-35/_import.txt4
-rw-r--r--npc/001-2-35/_warps.txt3
-rw-r--r--npc/001-2-35/mapflags.txt1
-rw-r--r--npc/001-2-36/_import.txt5
-rw-r--r--npc/001-2-36/_warps.txt3
-rw-r--r--npc/001-2-36/mapflags.txt1
-rw-r--r--npc/001-2-36/training_room_npc.txt165
-rw-r--r--npc/001-2-37/_import.txt6
-rw-r--r--npc/001-2-37/_savepoints.txt38
-rw-r--r--npc/001-2-37/_warps.txt4
-rw-r--r--npc/001-2-37/hammock.txt106
-rw-r--r--npc/001-2-37/mapflags.txt1
-rw-r--r--npc/001-2-38/_import.txt6
-rw-r--r--npc/001-2-38/_savepoints.txt38
-rw-r--r--npc/001-2-38/_warps.txt4
-rw-r--r--npc/001-2-38/hammock.txt106
-rw-r--r--npc/001-2-38/mapflags.txt1
-rw-r--r--npc/001-2-39/_import.txt5
-rw-r--r--npc/001-2-39/_warps.txt4
-rw-r--r--npc/001-2-39/mapflags.txt1
-rw-r--r--npc/001-2-39/qanon.txt22
-rw-r--r--npc/001-2-4/_import.txt7
-rw-r--r--npc/001-2-4/_warps.txt27
-rw-r--r--npc/001-2-4/books.txt102
-rw-r--r--npc/001-2-4/mapflags.txt1
-rw-r--r--npc/001-2-4/robin.txt65
-rw-r--r--npc/001-2-4/terry.txt23
-rw-r--r--npc/001-2-40/_import.txt5
-rw-r--r--npc/001-2-40/_warps.txt4
-rw-r--r--npc/001-2-40/mapflags.txt1
-rw-r--r--npc/001-2-40/trozz.txt21
-rw-r--r--npc/001-2-41/_import.txt5
-rw-r--r--npc/001-2-41/_warps.txt3
-rw-r--r--npc/001-2-41/edouard.txt169
-rw-r--r--npc/001-2-41/mapflags.txt1
-rw-r--r--npc/001-2-42/_import.txt3
-rw-r--r--npc/001-2-42/_warps.txt3
-rw-r--r--npc/001-2-5/_import.txt5
-rw-r--r--npc/001-2-5/_warps.txt3
-rw-r--r--npc/001-2-5/books.txt34
-rw-r--r--npc/001-2-5/mapflags.txt1
-rw-r--r--npc/001-2-6/_import.txt8
-rw-r--r--npc/001-2-6/_warps.txt3
-rw-r--r--npc/001-2-6/books.txt167
-rw-r--r--npc/001-2-6/christopher.txt69
-rw-r--r--npc/001-2-6/dolfina.txt21
-rw-r--r--npc/001-2-6/leonard.txt89
-rw-r--r--npc/001-2-6/mapflags.txt1
-rw-r--r--npc/001-2-7/_import.txt4
-rw-r--r--npc/001-2-7/_warps.txt5
-rw-r--r--npc/001-2-7/mapflags.txt1
-rw-r--r--npc/001-2-8/_import.txt4
-rw-r--r--npc/001-2-8/_warps.txt3
-rw-r--r--npc/001-2-8/mapflags.txt1
-rw-r--r--npc/001-2-9/_import.txt5
-rw-r--r--npc/001-2-9/_warps.txt3
-rw-r--r--npc/001-2-9/janus.txt170
-rw-r--r--npc/001-2-9/mapflags.txt1
-rw-r--r--npc/001-3-0/_import.txt4
-rw-r--r--npc/001-3-0/_mobs.txt17
-rw-r--r--npc/001-3-0/_warps.txt8
-rw-r--r--npc/001-3-1/_import.txt3
-rw-r--r--npc/001-3-1/_warps.txt4
-rw-r--r--npc/008-1/_import.txt7
-rw-r--r--npc/008-1/_mobs.txt15
-rw-r--r--npc/008-1/_warps.txt13
-rw-r--r--npc/008-1/confused-tree.txt957
-rw-r--r--npc/008-1/doors.txt6
-rw-r--r--npc/008-1/mapflags.txt1
-rw-r--r--npc/008-1/wateranimation.txt9
-rw-r--r--npc/008-2-0/_import.txt5
-rw-r--r--npc/008-2-0/_savepoints.txt11
-rw-r--r--npc/008-2-0/_warps.txt4
-rw-r--r--npc/008-2-0/mapflags.txt1
-rw-r--r--npc/008-2-1/_import.txt5
-rw-r--r--npc/008-2-1/_savepoints.txt11
-rw-r--r--npc/008-2-1/_warps.txt4
-rw-r--r--npc/008-2-1/mapflags.txt1
-rw-r--r--npc/008-2-10/_import.txt4
-rw-r--r--npc/008-2-10/_warps.txt4
-rw-r--r--npc/008-2-10/mapflags.txt1
-rw-r--r--npc/008-2-11/_import.txt5
-rw-r--r--npc/008-2-11/_savepoints.txt20
-rw-r--r--npc/008-2-11/_warps.txt3
-rw-r--r--npc/008-2-11/mapflags.txt1
-rw-r--r--npc/008-2-12/_import.txt4
-rw-r--r--npc/008-2-12/_warps.txt4
-rw-r--r--npc/008-2-12/mapflags.txt1
-rw-r--r--npc/008-2-13/_import.txt5
-rw-r--r--npc/008-2-13/_savepoints.txt38
-rw-r--r--npc/008-2-13/_warps.txt4
-rw-r--r--npc/008-2-13/mapflags.txt1
-rw-r--r--npc/008-2-14/_import.txt5
-rw-r--r--npc/008-2-14/_savepoints.txt11
-rw-r--r--npc/008-2-14/_warps.txt3
-rw-r--r--npc/008-2-14/mapflags.txt1
-rw-r--r--npc/008-2-2/_import.txt4
-rw-r--r--npc/008-2-2/_warps.txt6
-rw-r--r--npc/008-2-2/mapflags.txt1
-rw-r--r--npc/008-2-3/_import.txt4
-rw-r--r--npc/008-2-3/_warps.txt3
-rw-r--r--npc/008-2-3/mapflags.txt1
-rw-r--r--npc/008-2-4/_import.txt5
-rw-r--r--npc/008-2-4/_savepoints.txt11
-rw-r--r--npc/008-2-4/_warps.txt3
-rw-r--r--npc/008-2-4/mapflags.txt1
-rw-r--r--npc/008-2-5/_import.txt4
-rw-r--r--npc/008-2-5/_warps.txt3
-rw-r--r--npc/008-2-5/mapflags.txt1
-rw-r--r--npc/008-2-6/_import.txt4
-rw-r--r--npc/008-2-6/_warps.txt3
-rw-r--r--npc/008-2-6/mapflags.txt1
-rw-r--r--npc/008-2-7/_import.txt5
-rw-r--r--npc/008-2-7/_savepoints.txt11
-rw-r--r--npc/008-2-7/_warps.txt3
-rw-r--r--npc/008-2-7/mapflags.txt1
-rw-r--r--npc/008-2-8/_import.txt4
-rw-r--r--npc/008-2-8/_warps.txt3
-rw-r--r--npc/008-2-8/mapflags.txt1
-rw-r--r--npc/008-2-9/_import.txt5
-rw-r--r--npc/008-2-9/_savepoints.txt11
-rw-r--r--npc/008-2-9/_warps.txt3
-rw-r--r--npc/008-2-9/mapflags.txt1
-rw-r--r--npc/029-1/_import.txt5
-rw-r--r--npc/029-1/_mobs.txt39
-rw-r--r--npc/029-1/_warps.txt3
-rw-r--r--npc/029-1/mapflags.txt1
-rw-r--r--npc/_import.txt76
-rw-r--r--npc/commands/debug-look.txt102
-rw-r--r--npc/commands/debug-preset.txt246
-rw-r--r--npc/commands/debug-quest.txt157
-rw-r--r--npc/commands/debug-skill.txt81
-rw-r--r--npc/commands/debug.txt143
-rw-r--r--npc/commands/event.txt57
-rw-r--r--npc/commands/motd.txt193
-rw-r--r--npc/commands/music.txt46
-rw-r--r--npc/commands/rate-management.txt107
-rw-r--r--npc/commands/scheduled-broadcasts.txt225
-rw-r--r--npc/commands/super-menu.txt66
-rw-r--r--npc/commands/warp.txt116
-rw-r--r--npc/commands/zeny.txt98
-rw-r--r--npc/config/hairstyle_config.txt24
-rw-r--r--npc/dev/ci_test.txt47
-rw-r--r--npc/dev/test.txt814
-rw-r--r--npc/functions/RNGesus.txt23
-rw-r--r--npc/functions/array.txt410
-rw-r--r--npc/functions/asklanguage.txt80
-rw-r--r--npc/functions/asleep.txt19
-rw-r--r--npc/functions/bank.txt134
-rw-r--r--npc/functions/barber.txt110
-rw-r--r--npc/functions/beds.txt30
-rw-r--r--npc/functions/clientversion.txt20
-rw-r--r--npc/functions/confused-tree-dict.txt560
-rw-r--r--npc/functions/doors.txt59
-rw-r--r--npc/functions/fishing.txt294
-rw-r--r--npc/functions/game-rules.txt59
-rw-r--r--npc/functions/goodbye.txt152
-rw-r--r--npc/functions/hammocks.txt50
-rw-r--r--npc/functions/harbours.txt39
-rw-r--r--npc/functions/hello.txt23
-rw-r--r--npc/functions/input.txt66
-rw-r--r--npc/functions/inventoryplace.txt37
-rw-r--r--npc/functions/legiontalk.txt66
-rw-r--r--npc/functions/main.txt215
-rw-r--r--npc/functions/marriage.txt293
-rw-r--r--npc/functions/masks.txt68
-rw-r--r--npc/functions/math.txt40
-rw-r--r--npc/functions/mouboofunc.txt89
-rw-r--r--npc/functions/npcmove.txt142
-rw-r--r--npc/functions/npcmovegraph.txt485
-rw-r--r--npc/functions/openbook.txt36
-rw-r--r--npc/functions/permissions.txt35
-rw-r--r--npc/functions/quest-debug/000-ShipQuests_Julia.txt37
-rw-r--r--npc/functions/quest-debug/001-ShipQuests_Arpan.txt27
-rw-r--r--npc/functions/quest-debug/002-ShipQuests_Alige.txt27
-rw-r--r--npc/functions/quest-debug/003-ShipQuests_Peter.txt30
-rw-r--r--npc/functions/quest-debug/004-ShipQuests_Nard.txt38
-rw-r--r--npc/functions/quest-debug/005-ShipQuests_Knife.txt25
-rw-r--r--npc/functions/quest-debug/006-ShipQuests_ArpanMoney.txt26
-rw-r--r--npc/functions/quest-debug/007-ShipQuests_Door.txt25
-rw-r--r--npc/functions/quest-debug/008-ShipQuests_Couwan.txt26
-rw-r--r--npc/functions/quest-debug/009-ShipQuests_TreasureChest.txt25
-rw-r--r--npc/functions/quest-debug/010-ShipQuests_Ale.txt25
-rw-r--r--npc/functions/quest-debug/011-ShipQuests_Astapolos.txt25
-rw-r--r--npc/functions/quest-debug/012-ShipQuests_Gulukan.txt25
-rw-r--r--npc/functions/quest-debug/013-ShipQuests_Jalad.txt25
-rw-r--r--npc/functions/quest-debug/014-ShipQuests_QMuller.txt25
-rw-r--r--npc/functions/quest-debug/015-ShipQuests_Tibbo.txt25
-rw-r--r--npc/functions/quest-debug/016-ShipQuests_Gugli.txt48
-rw-r--r--npc/functions/quest-debug/017-ShipQuests_ChefGado.txt30
-rw-r--r--npc/functions/quest-debug/018-General_Cookies.txt25
-rw-r--r--npc/functions/quest-debug/019-ArtisQuests_LazyBrother.txt28
-rw-r--r--npc/functions/quest-debug/020-ArtisQuests_Urchin.txt26
-rw-r--r--npc/functions/quest-debug/021-ArtisQuests_CatchPiou.txt26
-rw-r--r--npc/functions/quest-debug/022-ArtisQuests_Fishman.txt26
-rw-r--r--npc/functions/quest-debug/023-ArtisQuests_QOnan.txt27
-rw-r--r--npc/functions/quest-debug/026-General_Rumly.txt27
-rw-r--r--npc/functions/quest-debug/027-ArtisQuests_Enora.txt49
-rw-r--r--npc/functions/quest-debug/028-General_Narrator.txt25
-rw-r--r--npc/functions/quest-debug/029-ArtisQuests_Fexil.txt27
-rw-r--r--npc/functions/quest-debug/030-ArtisQuests_Lloyd.txt25
-rw-r--r--npc/functions/quest-debug/031-General_Janus.txt31
-rw-r--r--npc/functions/quest-debug/032-ArtisQuests_MonaDad.txt25
-rw-r--r--npc/functions/quest-debug/033-Artis_Legion_Progress.txt30
-rw-r--r--npc/functions/quest-debug/functions.txt109
-rw-r--r--npc/functions/questgen.txt38
-rw-r--r--npc/functions/riddle.txt74
-rw-r--r--npc/functions/sailordialogue.txt53
-rw-r--r--npc/functions/sailortalk.txt37
-rw-r--r--npc/functions/savepoint.txt48
-rw-r--r--npc/functions/shops.txt13
-rw-r--r--npc/functions/string.txt195
-rw-r--r--npc/functions/time.txt108
-rw-r--r--npc/functions/timer.txt56
-rw-r--r--npc/functions/util.txt35
-rw-r--r--npc/functions/villagertalk.txt53
-rw-r--r--npc/items/croconut.txt72
-rw-r--r--npc/items/rand_sc_heal.txt85
-rw-r--r--npc/items/shovel.txt218
-rw-r--r--npc/re/scripts_main.conf4
-rw-r--r--npc/scripts.conf109
-rw-r--r--npc/test/_import.txt13
-rw-r--r--npc/test/_mobs.txt15
-rw-r--r--npc/test/mapflags.txt2
-rw-r--r--npc/test/npc1.txt670
-rw-r--r--npc/test/npc2.txt35
-rw-r--r--npc/test/npc3.txt7
-rw-r--r--npc/test/npc4.txt30
-rw-r--r--npc/test/npc5.txt34
-rw-r--r--npc/test/npc6.txt23
-rw-r--r--npc/test/npcmarriage.txt19
-rw-r--r--npc/test/test1.txt76
-rw-r--r--npc/test/test2.txt13
-rw-r--r--npc/testbg/_import.txt3
-rw-r--r--npc/testbg/mapflags.txt1
484 files changed, 25948 insertions, 0 deletions
diff --git a/npc/000-0-0/import.txt b/npc/000-0-0/import.txt
new file mode 100644
index 000000000..039280fe3
--- /dev/null
+++ b/npc/000-0-0/import.txt
@@ -0,0 +1,5 @@
+// Map 000-0-0: Sailor's Room
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/000-0-0/mapflags.txt",
+"npc/000-0-0/q'onan.txt",
+"npc/000-0-0/sailors.txt",
diff --git a/npc/000-0-0/mapflags.txt b/npc/000-0-0/mapflags.txt
new file mode 100644
index 000000000..0ed6ce16b
--- /dev/null
+++ b/npc/000-0-0/mapflags.txt
@@ -0,0 +1 @@
+000-0-0 mapflag invisible
diff --git a/npc/000-0-0/qonan.txt b/npc/000-0-0/qonan.txt
new file mode 100644
index 000000000..d262c1ca1
--- /dev/null
+++ b/npc/000-0-0/qonan.txt
@@ -0,0 +1,15 @@
+// Evol scripts.
+// Authors:
+// Alige
+// Vasily_Makarov
+// Description:
+// Sleeping and snoring NPC.
+
+000-0-0,29,28,0 script Q'Onan#000-0-0 NPC_ORC_SAILOR,{
+ asleep;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ end;
+}
diff --git a/npc/000-0-0/sailors.txt b/npc/000-0-0/sailors.txt
new file mode 100644
index 000000000..5805994c9
--- /dev/null
+++ b/npc/000-0-0/sailors.txt
@@ -0,0 +1,85 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Qwerty Dragon
+// Description:
+// Introduction scene where two sailors talk about how the player was found on his raft.
+// Elmo will handle dialogs between both NPCs.
+
+000-0-0,26,23,0 script Elmo#sailors NPC_ELMO,{
+
+OnTalk:
+ setcamnpc;
+ mesn "Elmo";
+ mesq lg("This girl is lucky we found her before a shark did. I have no idea where she comes from. By the way, did you see the logo on her raft?", "This guy is lucky we found him before a shark did. I have no idea where he comes from. By the way, did you see the logo on his raft?");
+ next;
+
+ mesn "Magic Arpan";
+ mesq lg("Yeye, it's the logo of the Legion of Aemil in Esperia! I wonder what this yoiis was doing so far away from the coast.");
+ next;
+
+ mesn "Elmo";
+ mesq l("I wonder too...");
+ next;
+
+ mesn "Magic Arpan";
+ mesq lg("Maybe she was one of those who got lost last month. She could be the yoiis from Esperia who got a secret diplomatic mission from the Legion of Aemil!", "Maybe he was one of those who got lost last month? He could be the yoiis from Esperia who got a secret diplomatic mission from the Legion of Aemil!");
+ next;
+
+ mesn "Elmo";
+ mesq l("Makes sense. Do you think we should inform the capt'n about it?");
+ next;
+
+ mesn "Magic Arpan";
+ mesq l("Yeye.");
+ next;
+
+ mesn "Elmo";
+ mesq lg("Alright, I'm going to his room, keep an eye on her, we still don't know if she's friend or foe...", "Alright, I'm going to his room, keep an eye on him, we still don't know if he's friend or foe...");
+ next;
+
+ mesn "Magic Arpan";
+ mesq l("I will yaying do.");
+ next;
+
+ mesn "Elmo";
+ mesq lg("Oh, and give her some clothes, the poor girl, the ones she had were in an even worse condition than the ones we have.", "Oh, and give him some clothes, the poor guy, the ones he had were in an even worse condition than the ones we have.");
+ next;
+
+ mesn "Magic Arpan";
+ mesq l("Yayayaya, it's the first time someone is dressed worse than us!");
+ next;
+
+ mesn "Elmo";
+ mesq l("Hehe... Ok, I'm going to inform the capt'n up there.");
+ next;
+
+ mesn "Magic Arpan";
+ mesq lg("I'll give her everything she needs, don't worry.", "I'll give him everything he needs, don't worry.");
+ next;
+
+ mesn "Elmo";
+ mesq lg("Ok, I think she's waking up, go see her.", "Ok, I think he's waking up, go see him.");
+ next;
+
+ restorecam;
+ adddefaultskills;
+ setq General_Narrator, 0;
+ warp "000-2-1", 50, 38;
+ savepoint "000-2-1", 50, 38;
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ end;
+}
+
+000-0-0,25,23,0 script Magic Arpan#sailors NPC_MAGIC_ARPAN,{
+ doevent "Elmo#sailors::OnTalk";
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ end;
+}
diff --git a/npc/000-0-1/_import.txt b/npc/000-0-1/_import.txt
new file mode 100644
index 000000000..ed7839379
--- /dev/null
+++ b/npc/000-0-1/_import.txt
@@ -0,0 +1,4 @@
+// Map 000-0-1: Sailor's Room
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/000-0-1/mapflags.txt",
+"npc/000-0-1/narrator.txt",
diff --git a/npc/000-0-1/mapflags.txt b/npc/000-0-1/mapflags.txt
new file mode 100644
index 000000000..04d1aea50
--- /dev/null
+++ b/npc/000-0-1/mapflags.txt
@@ -0,0 +1 @@
+000-0-1 mapflag invisible
diff --git a/npc/000-0-1/narrator.txt b/npc/000-0-1/narrator.txt
new file mode 100644
index 000000000..5c7e4788d
--- /dev/null
+++ b/npc/000-0-1/narrator.txt
@@ -0,0 +1,37 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Narrator explain to the player that he is dreaming.
+// Variable:
+// 0 General_Narrator
+// Values:
+// 0 PC is in the game introduction.
+// 1 PC arrived Artis.
+
+000-0-1,25,28,0 script Narrator#000-0-1 NPC_NARRATOR,{
+
+ narrator S_LAST_NEXT,
+ l("Look, we finally meet."),
+ l("I think that you already understood, you are asleep."),
+ l("The ship, La Johanne, has left Drasil Island, finally."),
+ l("Nard and his crew are taking us to the city of Artis."),
+ l("There are a lot of things you must be wondering about."),
+ l("So, search for answers."),
+ l("..."),
+ l("Ah, seagulls. We are arriving."),
+ l("..."),
+ l("Wake-up!");
+
+ if (countitem(JohanneKey) == 1) delitem JohanneKey, 1;
+ setq General_Narrator, 1;
+ setq ShipQuests_Nard, 6;
+ savepoint "001-2-22", 50, 38;
+ warp "001-2-22", 50, 38;
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/000-0/_import.txt b/npc/000-0/_import.txt
new file mode 100644
index 000000000..75f2626bf
--- /dev/null
+++ b/npc/000-0/_import.txt
@@ -0,0 +1,4 @@
+// Map 000-0: Oceania
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/000-0/mapflags.txt",
+"npc/000-0/sailors.txt",
diff --git a/npc/000-0/mapflags.txt b/npc/000-0/mapflags.txt
new file mode 100644
index 000000000..e956447ee
--- /dev/null
+++ b/npc/000-0/mapflags.txt
@@ -0,0 +1 @@
+000-0 mapflag invisible
diff --git a/npc/000-0/sailors.txt b/npc/000-0/sailors.txt
new file mode 100644
index 000000000..d31c84391
--- /dev/null
+++ b/npc/000-0/sailors.txt
@@ -0,0 +1,80 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Qwerty Dragon
+// Reid
+// Vasily_Makarov
+// Description:
+// Starting script of Evol Online.
+
+000-0,23,20,0 script Sailors NPC_SAILORS,6,6,{
+
+OnTouch:
+ checkclientversion;
+ .@lang = requestlang();
+ if (.@lang >= 0 && .@lang <= 9) Lang = .@lang;
+
+ mesn "Narrator";
+ mes col(l("You are on a raft, adrift in the sea."), 9);
+ next;
+ mes col(l("With hunger, thirst, and sleep as your only companions, you have the disturbing realization that you can't remember anything of your former life or identity."), 9);
+ next;
+ mes col(l("All of a sudden, you hear voices from above."), 9);
+ next;
+ mes col(l("Your body aches, even your hair hurts, and the bright daylight is painful."), 9);
+ next;
+ mes col(l("But still, you open your eyes and see a large ship before you!"), 9);
+ next;
+ mes col(l("Aboard stand sailors trying to communicate with you."), 9);
+ next;
+
+ setcamnpc "Sailors", -64, -32;
+ mesn "Kralog Voice";
+ mesq lg("Hey Frenchy!");
+ next;
+
+ setcamnpc "Sailors", 0, -32;
+ mesn "Human Voice";
+ mesq lg("Why Frenchy? It's a Russian!");
+ next;
+
+ setcamnpc "Sailors", 144, -80;
+ mesn "Tritan Voice";
+ mesq lg("What are you guys saying ? It's a Yoiis!");
+ next;
+
+ setcamnpc;
+ mesn "Raijin Voice";
+ mesq lg("You stupid, she's English, look at the shape of her head.", "You stupid, he's English, look at the shape of his head.");
+ next;
+ mesq l("Hey you! Can you hear us? Are you okay?");
+ next;
+ restorecam;
+
+ asklanguage(LANG_ON_SEA);
+
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq lg("Oh, she's still alive!", "Oh, he's still alive!");
+ next;
+ setcamnpc "Sailors", 144, -80;
+ mesq lg("This girl needs help, we need to rescue her!", "This guy needs help, we need to rescue him!");
+ next;
+ restorecam;
+
+ mesn "Narrator";
+ mes col(l("The sailors take you aboard their ship."), 9);
+ next;
+ mes col(l("Click on the NPCs (Non-Player Characters) around you to continue the introduction."), 9);
+ next;
+
+ warp "000-0-0", 26, 28;
+
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ end;
+}
diff --git a/npc/000-1/_import.txt b/npc/000-1/_import.txt
new file mode 100644
index 000000000..f103452c4
--- /dev/null
+++ b/npc/000-1/_import.txt
@@ -0,0 +1,23 @@
+// Map 000-1: Drasil Island
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/000-1/_mobs.txt",
+"npc/000-1/_warps.txt",
+"npc/000-1/ale.txt",
+"npc/000-1/astapolos.txt",
+"npc/000-1/chest.txt",
+"npc/000-1/couwan.txt",
+"npc/000-1/darlin.txt",
+"npc/000-1/fexil.txt",
+"npc/000-1/gugli.txt",
+"npc/000-1/gulukan.txt",
+"npc/000-1/jalad.txt",
+"npc/000-1/lean.txt",
+"npc/000-1/mapflags.txt",
+"npc/000-1/maxe.txt",
+"npc/000-1/muller.txt",
+"npc/000-1/panels.txt",
+"npc/000-1/sapartan.txt",
+"npc/000-1/shop.txt",
+"npc/000-1/silvio.txt",
+"npc/000-1/tarlan.txt",
+"npc/000-1/tibbo.txt",
diff --git a/npc/000-1/_mobs.txt b/npc/000-1/_mobs.txt
new file mode 100644
index 000000000..9bd9ea81c
--- /dev/null
+++ b/npc/000-1/_mobs.txt
@@ -0,0 +1,39 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-1: Drasil Island mobs
+000-1,28,49,6,9 monster Tortuga 1004,3,16000,120000
+000-1,58,118,34,14 monster Tortuga 1004,4,35000,300000
+000-1,71,95,4,12 monster Tortuga 1004,1,35000,300000
+000-1,52,92,4,17 monster Tortuga 1004,2,35000,300000
+000-1,37,66,11,5 monster Tortuga 1004,2,35000,120000
+000-1,42,41,9,16 monster Tortuga 1004,2,35000,120000
+000-1,87,37,12,11 monster Tortuga 1004,3,35000,120000
+000-1,44,75,2,1 monster Little Blub 1007,2,25000,120000
+000-1,61,64,7,10 monster Little Blub 1007,2,25000,120000
+000-1,62,25,10,4 monster Little Blub 1007,2,25000,120000
+000-1,87,69,4,3 monster Blub 1008,1,60000,120000
+000-1,85,33,2,3 monster Little Blub 1007,1,25000,120000
+000-1,85,58,14,9 monster Little Blub 1007,2,35000,120000
+000-1,48,61,9,6 monster Little Blub 1007,1,35000,120000
+000-1,28,48,3,5 monster Little Blub 1007,1,35000,120000
+000-1,35,50,0,1 monster Plushroom Field 1011,1,35000,150000
+000-1,54,115,0,1 monster Plushroom Field 1011,1,35000,150000
+000-1,63,80,4,2 monster Plushroom Field 1011,1,35000,150000
+000-1,54,64,0,2 monster Plushroom Field 1011,1,35000,150000
+000-1,78,58,4,5 monster Plushroom Field 1011,2,35000,150000
+000-1,71,62,1,1 monster Plushroom Field 1011,1,35000,150000
+000-1,32,116,8,9 monster Croc 1006,2,35000,300000
+000-1,63,31,10,3 monster Croc 1006,1,35000,300000
+000-1,76,68,1,1 monster Croc 1006,1,35000,300000
+000-1,52,92,4,17 monster Croc 1006,1,35000,300000
+000-1,71,77,4,4 monster Croc 1006,1,35000,300000
+000-1,0,0,0,0 monster Piou 1002,4,60000,15000
+000-1,78,115,0,0 monster Crocotree 1010,1,420000,240000
+000-1,57,104,0,0 monster Crocotree 1010,1,420000,240000
+000-1,39,112,0,0 monster Crocotree 1010,1,420000,240000
+000-1,67,93,0,0 monster Crocotree 1010,1,420000,240000
+000-1,53,77,0,0 monster Crocotree 1010,1,420000,240000
+000-1,64,63,0,0 monster Crocotree 1010,1,420000,240000
+000-1,31,69,0,0 monster Crocotree 1010,1,420000,240000
+000-1,44,44,0,0 monster Crocotree 1010,1,420000,240000
+000-1,70,33,0,0 monster Crocotree 1010,1,420000,240000
+000-1,84,66,0,0 monster Crocotree 1010,1,420000,240000
diff --git a/npc/000-1/_warps.txt b/npc/000-1/_warps.txt
new file mode 100644
index 000000000..47b4fb420
--- /dev/null
+++ b/npc/000-1/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-1: Drasil Island warps
+000-1,94,100,0 warp #000-1_94_100 0,0,000-2-0,21,28
diff --git a/npc/000-1/ale.txt b/npc/000-1/ale.txt
new file mode 100644
index 000000000..0a37eb021
--- /dev/null
+++ b/npc/000-1/ale.txt
@@ -0,0 +1,110 @@
+// Evol scripts.
+// Authors:
+// Qwerty Dragon
+// Reid
+// Description:
+// Sailor part of the Gugli's quest.
+// Aquada box.
+
+000-1,55,23,0 script Ale#000-1 NPC_DEMON_MAN_SITTING,{
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+ .@g = getq(ShipQuests_Gugli);
+ if (.@g == 0) goto L_NoTask;
+
+ .@q = getq(ShipQuests_Ale);
+ if (.@q == 1) goto L_CallFunc;
+
+ mesn;
+ mesq l("Ouch...");
+ next;
+ mesq l("These heavy boxes are killing me, I can't feel my arms anymore!");
+ next;
+
+ menu
+ lg("Gugli sent me down here to help you."), -,
+ l("See you aboard."), L_Quit;
+
+ mes "";
+ mesn;
+ mesq l("Really? That's kind of you, I accept your help!");
+ next;
+ mesq l("Hmm... Let's see, take this one.");
+ next;
+
+ inventoryplace AquadaBox, 1;
+
+ setq ShipQuests_Ale, 1;
+ getitem AquadaBox, 1;
+
+ mes "";
+ mesn;
+ mesq l("I will take care of the other ones don't worry.");
+
+ close;
+
+L_CallFunc:
+ sailorfood;
+
+ menu
+ rif(getq(ShipQuests_Gugli) > 1, l("Task is done.")), L_TaskDone,
+ rif(getq(ShipQuests_Ale) == 1 && (getq(ShipQuests_Astapolos) == 0 || getq(ShipQuests_Gulukan) == 0 || getq(ShipQuests_Jalad) == 0 || getq(ShipQuests_QMuller) == 0 || getq(ShipQuests_Tibbo) == 0), l("I'm still busy, I need to find the other sailors.")), -;
+
+ mes "";
+ mesn;
+ mesq l("Who are you looking for?");
+ next;
+
+ menu
+ rif(getq(ShipQuests_Astapolos) == 0, l("Astapolos.")), L_Bottom,
+ rif(getq(ShipQuests_Gulukan) == 0, l("Gulukan.")), L_Bottom,
+ rif(getq(ShipQuests_Jalad) == 0, l("Jalad.")), L_Jalad,
+ rif(getq(ShipQuests_QMuller) == 0, l("Q'Muller.")), L_Bottom,
+ rif(getq(ShipQuests_Tibbo) == 0, l("Tibbo.")), L_Bottom,
+ l("Nobody."), L_Quit;
+
+L_Bottom:
+ mes "";
+ mesn;
+ mesq l("I've seen him down around the southern area of the island, ask Jalad for more information.");
+
+ close;
+
+L_Jalad:
+ setcamnpc "Jalad";
+
+ next;
+ mesn;
+ mesq l("Look, here he is!");
+ next;
+
+ restorecam;
+
+ close;
+
+L_NoTask:
+ mes "";
+ mesn;
+ mesq l("Ouch... These boxes are so heavy!");
+
+ close;
+
+L_TaskDone:
+ mes "";
+ mesn;
+ mesq l("That's good to hear!");
+
+ close;
+
+L_Quit:
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/astapolos.txt b/npc/000-1/astapolos.txt
new file mode 100644
index 000000000..df64b36b0
--- /dev/null
+++ b/npc/000-1/astapolos.txt
@@ -0,0 +1,166 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Reid
+// Description:
+// Sailor part of the Gugli's quest.
+// Croconut box.
+
+000-1,22,50,0 script Astapolos NPC_ELVEN_MAN_RED,{
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+ .@g = getq(ShipQuests_Gugli);
+ if (.@g == 0) goto L_NoTask;
+
+ .@q = getq(ShipQuests_Astapolos);
+ if (.@q == 1) goto L_CallFunc;
+
+ mesn;
+ mesq l("So finally someone has came to visit me?");
+ next;
+
+ select
+ lg("Actually, I came here to work on my task.");
+
+ mes "";
+ mesn;
+ mesq l("Oh, I see. That's right. Why should someone come here to see me, seriously?");
+ next;
+ mesq l("Do you think this is fair? They sent me down here alone, far away from everyone.");
+ next;
+
+ menu
+ lg("I'm sorry for your situation. They should alternate shifts with other sailors from time to time."), -,
+ l("Well if you are whining like that all the time, then I think there is a reason behind their choice."), L_Whyning;
+
+ mes "";
+ mesn;
+ mesq l("Exactly. Even our task is ridiculous. Why should we collect food down here if we have plenty of those tasty and soft rattos inside our ship, waiting just to be hunted and cooked?");
+ next;
+
+ menu
+ l("You... You eat... rattos? I think you're just a fool."), L_Whyning,
+ l("Oh... eating rattos. Sounds... ehm... Delicious, yes."), -;
+
+ mes "";
+ mesn;
+ mesq l("You like them, don't you? Just speak with Peter then. He is on the second deck of the ship. He will send you downstairs to the hold, where you will find a furry meal!");
+ next;
+ mesq lg("Oh, but you didn't come here to talk about that, am I right?");
+ next;
+
+ select
+ lg("Actually, I was here to help you with those boxes. Can I bring one of them back to Gugli?");
+
+ mes "";
+ mesn;
+ mesq l("Usually I don't allow anyone to touch my boxes but...");
+ next;
+ mesq lg("You have been so nice to me. So please, take one.");
+ next;
+
+ inventoryplace CroconutBox, 1;
+
+ setq ShipQuests_Astapolos, 1;
+ getitem CroconutBox, 1;
+
+ mes "";
+ mesn;
+ mesq l("Good luck! And remember to visit Peter and our little furry friends whenever you return back onboard!");
+
+ close;
+
+L_CallFunc:
+ sailorfood;
+
+ menu
+ rif(getq(ShipQuests_Gugli) > 1, l("Task is done.")), L_TaskDone,
+ rif(getq(ShipQuests_Astapolos) == 1 && (getq(ShipQuests_Ale) == 0 || getq(ShipQuests_Gulukan) == 0 || getq(ShipQuests_Jalad) == 0 || getq(ShipQuests_QMuller) == 0 || getq(ShipQuests_Tibbo) == 0), l("I'm still busy, I need to find the other sailors.")), -,
+ l("How are things going?"), L_HowAreYou,
+ l("Who are you?"), L_Who;
+
+ mes "";
+ mesn;
+ mesq l("Who are you looking for?");
+ next;
+
+ menu
+ rif(getq(ShipQuests_Ale) == 0, l("Ale.")), L_Top,
+ rif(getq(ShipQuests_Gulukan) == 0, l("Gulukan.")), L_Bottom,
+ rif(getq(ShipQuests_Jalad) == 0, l("Jalad.")), L_Top,
+ rif(getq(ShipQuests_QMuller) == 0, l("Q'Muller.")), L_Bottom,
+ rif(getq(ShipQuests_Tibbo) == 0, l("Tibbo.")), L_Bottom,
+ l("Nobody."), -;
+
+ closedialog;
+ close;
+
+L_HowAreYou:
+
+ mes "";
+ mesn;
+ mesq l("A sunny and hot day,");
+ next;
+ mesq l("a quiet place,");
+ next;
+ mesq l("a ground!");
+ next;
+ mesq l("I hope that answers your question.") + " " + l("Hehe!");
+
+ close;
+
+L_Who:
+ mes "";
+ mesn;
+ mesq l("My name is Astapolos. Q'Muller and I joined Nard's crew a few years ago when it was just a little merchant ship.");
+ next;
+ mesq l("At that time, we were selling crab food on our old mushroom island.");
+ next;
+ mesq l("And now I'm a sailor, as you can see!");
+
+ close;
+
+L_Bottom:
+ mes "";
+ mesn;
+ mesq l("I've seen him at the southern part of the island, check around.");
+
+ close;
+
+L_Top:
+ mes "";
+ mesn;
+ mesq l("I've seen him at the northern part of the island.");
+ next;
+ mesq l("You should walk to the north.");
+
+ close;
+
+L_NoTask:
+ npctalk3 l("Just leave me alone.");
+
+ closedialog;
+ close;
+
+L_TaskDone:
+ mes "";
+ mesn;
+ mesq l("Perfect!");
+
+ close;
+
+L_Whyning:
+ npctalk3 l("Then leave me alone.");
+
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/chest.txt b/npc/000-1/chest.txt
new file mode 100644
index 000000000..46f626a34
--- /dev/null
+++ b/npc/000-1/chest.txt
@@ -0,0 +1,65 @@
+// Evol scripts.
+// Authors:
+// 4144
+// gumi
+// Hal9000
+// Reid
+// Description:
+// A treasure chest, with... Treasures inside!
+// Variable:
+// x ShipQuests_TreasureChest
+// Values:
+// 0 Treasure Chest has not been opened yet.
+// 1 Treasure Chest has been opened.
+
+000-1,83,70,0 script Chest#000-1 NPC_CHEST,3,3,{
+
+ if (.busy == false)
+ {
+ if (getq(ShipQuests_TreasureChest) == 0)
+ {
+ inventoryplace OldBook, 1;
+ setq ShipQuests_TreasureChest, 1;
+ npctalk3 l("Chest opened.");
+ Zeny += 100;
+ getitem OldBook, 1;
+ }
+
+ specialeffect(.dir == 0 ? 24 : 25, AREA, getnpcid(0)); // closed ? opening : closing
+ .dir = .dir == 0 ? 2 : 6; // closed ? opening : closing
+ .busy = true; // lock until available again
+ initnpctimer;
+ }
+ end;
+
+OnTimer160:
+ .dir = .dir == 6 ? 0 : 4; // closing ? closed : open
+ end;
+
+OnTimer500:
+ .busy = false; // unlock
+
+ if (.dir == 0)
+ {
+ stopnpctimer; // stop here if the chest is closed
+ }
+ end;
+
+OnUnTouch:
+ if (getareausers(.x - 3, .y - 3, .x + 3, .y + 3) > 0 || .dir == 0)
+ {
+ end;
+ }
+OnTimer30000:
+ .busy = true;
+ .dir = 6; // closing
+ specialeffect(25, AREA, getnpcid(0)); // closing
+ setnpctimer 0;
+OnTouch:
+ end;
+
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/couwan.txt b/npc/000-1/couwan.txt
new file mode 100644
index 000000000..0d2317060
--- /dev/null
+++ b/npc/000-1/couwan.txt
@@ -0,0 +1,95 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Reid
+// Description:
+// Couwan is trying to scam the player.
+// Variable:
+// x ShipQuests_Couwan
+// Values:
+// 0 Never talked with Couwan.
+// 1 Spoke, and received the quest scam.
+// 2 Done quest scam.
+
+000-1,89,36,0 script Couwan NPC_TRITAN_MAN_SAILOR,{
+ .@q = getq(ShipQuests_Couwan);
+ if (.@q == 1)
+ {
+ mesn;
+ mesq l("What are you looking at?");
+ next;
+ mesq l("Yeye still have my box? Stare less and work more. Go give it to Gugli!");
+ close;
+ }
+ else if (.@q > 1)
+ {
+ mesn;
+ mesq l("What are you looking at?");
+ next;
+ mesq l("Yeye gave my box to Gugli? Nice, nice yeye!");
+ close;
+ }
+
+ mesn;
+ mesq l("Hello yeye.");
+ next;
+ mesq l("Look how splendid this landscape is!");
+ next;
+
+ switch(select(
+ l("Very nice, indeed!"),
+ l("I don't see anything else other than... water?")))
+ {
+ case 2:
+ mes "";
+ mesn;
+ mesq l("Yeye's brain is probably still full of sea water if yeye can't see the beauty of this place.");
+ next;
+ mesq l("Stupid yeye...");
+ close;
+ }
+
+ mes "";
+ mesn;
+ mesq l("Yeye got good eyes and seem to have fully recovered from your injuries...");
+ next;
+ mesq l("Hey, could yeye please take my box of fish to Gugli?");
+ next;
+
+ switch(select(
+ l("Sure, but what will I get in exchange?"),
+ l("I'm sorry, I don't have time right now.")))
+ {
+ case 2:
+ mes "";
+ mesn;
+ mesq l("Stupid yeye...");
+ break;
+
+ case 255:
+ break;
+
+ default:
+ mes "";
+ mesn;
+ mesq l("Yeye ask too much but do too little. Take this box and stop talking.");
+ next;
+
+ inventoryplace FishBox, 1;
+ mesn "Narrator";
+ mes col(l("Couwan hands you a box full of fish."), 9);
+ getitem FishBox, 1;
+ next;
+ mes col(l("The sailor turns his back to you."), 9);
+
+ setq ShipQuests_Couwan, 1;
+ break;
+ }
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/darlin.txt b/npc/000-1/darlin.txt
new file mode 100644
index 000000000..1288ad83e
--- /dev/null
+++ b/npc/000-1/darlin.txt
@@ -0,0 +1,149 @@
+// Evol scripts.
+// Authors:
+// Alige
+// Reid
+// Description:
+// Darlin talks from the top of the tall mast.
+// Variable:
+// x ShipQuests_TreasureChest
+// Values:
+// 0 Treasure Chest has not been opened yet.
+// 1 Treasure Chest has been opened.
+
+000-1,89,95,0 script Darlin NPC_RAIJIN_MAN,{
+ .@q = getq(ShipQuests_TreasureChest);
+
+ mesn;
+ setcamnpc;
+ mesq l("HEY! HEY YOU!");
+ next;
+ mesq l("CAN YOU HEAR ME?!");
+ next;
+ restorecam;
+
+ menu
+ l("Yes!"), -,
+ l("No!"), L_Quit;
+
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("GOOD!");
+ next;
+ mesq l("I WAS HERE WHEN THEY RESCUED YOU!");
+ next;
+ mesq l("DO YOU FEEL BETTER?!");
+ next;
+ restorecam;
+
+ menu
+ l("I do feel better!"), -,
+ l("Why don't you come down to talk?"), L_GoDown;
+
+ mes "";
+ menu
+ l("And you, how are you doing?"), -,
+ l("But I need to go, see you!"), L_Bye;
+
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("I AM DOING FINE!");
+ next;
+ mesq l("HEY, WHAT'S YOUR NAME?!");
+ next;
+ restorecam;
+
+ select
+ strcharinfo(0) + ".",
+ l("Maybe you can come down to talk?");
+
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("WHAT DID YOU SAY?!");
+ next;
+ mesq l("I DO NOT UNDERSTAND!");
+ next;
+ restorecam;
+
+ menu
+ l("I said... WHY DON'T YOU COME DOWN TO TALK?"), L_GoDown,
+ l("I SAID, SEE YOU LATER!"), L_Bye,
+ l("I'M CALLED, @@!", strtoupper(strcharinfo(0))), -;
+
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq strtoupper(strcharinfo(0)) + "? " + l("THAT'S A NICE NAME!");
+ next;
+ mesq l("SO WHAT'S UP?! WHAT ARE YOU DOING?!");
+ next;
+ restorecam;
+
+ menu
+ l("I'm looking for Gugli, where is he?"), -,
+ l("I need to go, sorry."), L_Bye;
+
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("OH, LOOK THERE!");
+ setcamnpc "Gugli";
+ next;
+ mesq l("HE IS AT THE BOTTOM OF THE SHIP, DOWN THE STAIRS. YOU CAN'T MISS HIM!");
+ next;
+ restorecam;
+
+ goto L_Quit;
+
+L_GoDown:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("I WOULD LOVE TO!");
+ next;
+ mesq l("BUT I CAN'T, I NEED TO KEEP AN EYE ON THE SEA, TO WARN THE CREW IF THERE HAPPENS TO BE SOME PIRATES AROUND!");
+ next;
+ mesq l("I ALSO AVOID THE DANGEROUS ANIMALS!");
+ next;
+ restorecam;
+
+ menu
+ l("Have you seen anything dangerous?"), -,
+ l("Interesting... I'll leave you to your task then!"), L_Bye;
+
+ mes "";
+ mesn;
+
+ if (.@q > 0) goto L_DangerAround;
+
+ setcamnpc;
+ mesq l("Oh no, but I've noticed a weird light on the other part of this island, I wonder what it could be...");
+ next;
+ restorecam;
+
+ goto L_Quit;
+
+L_Bye:
+ npctalk3 l("FINE, BYE!");
+
+ goto L_Quit;
+
+L_DangerAround:
+ setcamnpc;
+ mesq l("NOTHING ELSE OTHER THAN SHARKS AND AN ODD LIGHT!");
+ next;
+ restorecam;
+
+ goto L_Quit;
+
+L_Quit:
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 14;
+ end;
+}
diff --git a/npc/000-1/fexil.txt b/npc/000-1/fexil.txt
new file mode 100644
index 000000000..de72aec24
--- /dev/null
+++ b/npc/000-1/fexil.txt
@@ -0,0 +1,44 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Newbie merchant.
+
+000-1,83,98,0 script Fexil NPC_ELVEN_MAN_TRADER,{
+ mesn;
+ mesq lg("Greetings traveler.");
+ next;
+ mesq l("I have some clothes and other things for you at a fine price!");
+ next;
+ mesq l("What I sell comes from every corner of Gasaron. From Esperia to the Land of Fire!");
+ next;
+ mesq lg("Interested?");
+ next;
+
+ switch (select("Yes, why not.:I would rather sell some stuff.:No, Sorry."))
+ {
+ case 1:
+ mes "";
+ mesn;
+ mesq l("Good, take a look in the bag next to me then!");
+ close;
+
+ case 2:
+ closedialog;
+ shop "Bag#000-1";
+ close;
+
+ default:
+ mes "";
+ mesn;
+ mesq l("Oh... Well, I just started to trade... Thus my technique may not be the best.");
+ next;
+ mesq lg("Anyway, if you ever feel interested, just check my bag!");
+ close;
+ }
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/gugli.txt b/npc/000-1/gugli.txt
new file mode 100644
index 000000000..e9e0e0b07
--- /dev/null
+++ b/npc/000-1/gugli.txt
@@ -0,0 +1,249 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Reid
+// Description:
+// Elmo's twin
+// Charged of an important quest from Nard, he asks you to help other sailors to keep their box to the ship.
+// Variable:
+// 0 ShipQuests_Couwan
+// 1 ShipQuests_Nard
+// 2 ShipQuests_Gugli
+// Values:
+// 00 Never talked with Couwan.
+// 01 Spoke, and received the quest scam.
+// 02 Done quest scam.
+// 10 Introduction of the box and Nard. This is displayed when the player never spoke to Nard or his box.
+// 11 Nard spoke and gave access to the outdoor of the ship.
+// 12 Completed the quest.
+// 13 Opened the chest and finished the introduction.
+// 20 Never talked with Gugli.
+// 21 Gugli gives you the task.
+// 22 Gave all of the box to Gugli.
+
+000-1,85,108,0 script Gugli NPC_GUGLI,{
+
+ if (getq(ShipQuests_Couwan) == 1)
+ {
+ speech S_LAST_NEXT,
+ l("Great to see you! What can I do for you today?");
+ goto L_Menu;
+ }
+
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+OnTalk:
+ mesn;
+ .@nard = getq(ShipQuests_Nard);
+ .@gugli = getq(ShipQuests_Gugli);
+ .@gado = getq(ShipQuests_ChefGado);
+
+ if (.@nard > 3) goto L_AllComplete;
+ if (.@nard > 1 || .@gugli == 2) goto L_TaskCompleted;
+ if (.@gugli == 1) goto L_TaskGiven;
+
+ mesq lg("Hi @@, I heard the captain sent you down here, uh?", "Hi @@, I heard the captain sent you down here, uh?", strcharinfo(0));
+ next;
+ mesq l("What an unexpected pleasure, your help is always welcome!");
+ next;
+ mesq l("As you may know, we are explorers on a long distance voyage, and our swashbuckling mariners need to store enough food to survive. You don't know how dangerous the sea life can be.");
+ next;
+
+ select
+ l("Actually, I have an in-depth knowledge of this type of life.");
+
+ mes "";
+ mesn;
+ mesq lg("Well, even though you have been rescued by us, it doesn't make you an expert sailor, am I right?");
+ next;
+ mesq l("But let's talk about this island. We're docking here to find some fine quality goods.");
+ next;
+ mesq l("We usually dock around these small isles because they provide us some of the best food of all the archipelago.");
+ next;
+ mesq l("At the moment, our crew is busy collecting @@s, @@s and @@s.", getitemlink(Croconut), getitemlink(Plushroom), getitemlink(Aquada));
+ next;
+
+ select
+ l("So, what can I do for you?");
+
+ mes "";
+ mesn;
+ mesq l("Right! Ours is an earthsea realm. You see, sailors are swift at their tasks when out of sight of land, but docked by this verdant jewel, they have it so good, they are just taking too much time bringing all the food back to the ship. Maybe you can help them.");
+ next;
+ mesq l("The captain wants:");
+ mesq l("- 2 @@es", getitemlink(AquadaBox));
+ mesq l("- 2 @@es", getitemlink(CroconutBox));
+ mesq l("- 2 @@es", getitemlink(PlushroomBox));
+ next;
+ mesq l("Ask sailors around here they shouldn't be so far away.");
+ next;
+
+ setq ShipQuests_Gugli, 1;
+ close;
+
+L_TaskGiven:
+ mesq l("Great to see you! What can I do for you today?");
+ next;
+
+ if (getq(ShipQuests_Ale) == 1 && getq(ShipQuests_Astapolos) == 1 && getq(ShipQuests_Gulukan) == 1 && getq(ShipQuests_Jalad) == 1 && getq(ShipQuests_QMuller) == 1 && getq(ShipQuests_Tibbo) == 1) goto L_MenuDone;
+
+L_Menu:
+ menu
+ rif(getq(ShipQuests_Couwan) == 1, l("Couwan gave me this box, it is for you.")), L_Couwan,
+ rif(countitem(AquadaBox) > 0 || countitem(CroconutBox) > 0 || countitem(PlushroomBox) > 0, l("I have some food for you.")), L_CollectSmthing,
+ rif(getq(ShipQuests_Gugli) < 2, l("Who should I search for?")), L_SailorNames,
+ rif(getq(ShipQuests_Gugli) < 2, l("Where can I find your crew?")), L_Location,
+ l("Bye!"), L_Quit;
+
+L_MenuDone:
+ menu
+ rif(getq(ShipQuests_Couwan) == 1, l("Couwan gave me this box, it is for you.")), L_Couwan,
+ l("I have collected all the boxes you needed."), L_TaskDone,
+ l("See you!"), L_Quit;
+
+L_SailorNames:
+ mes "";
+ mesn;
+ mesq l("Ale and Tibbo should bring 2 boxes of @@s, Astapolos and Gulukan 2 of @@s and Jalad and Q'Muller were charged of the boxes of @@s.", getitemlink(Aquada), getitemlink(Croconut), getitemlink(Plushroom));
+ next;
+ mesq l("Do you need any other information?");
+ next;
+
+ goto L_Menu;
+
+L_CollectSmthing:
+ mes "";
+ mesn;
+ mesq l("Good job!");
+ next;
+
+ delitem AquadaBox, countitem(AquadaBox);
+ delitem CroconutBox, countitem(CroconutBox);
+ delitem PlushroomBox, countitem(PlushroomBox);
+
+ mesq l("You still need to give me boxes from: ");
+ if (getq(ShipQuests_Astapolos) == 0) mesq l("- Astapolos");
+ if (getq(ShipQuests_Ale) == 0) mesq l("- Ale");
+ if (getq(ShipQuests_Gulukan) == 0) mesq l("- Gulukan");
+ if (getq(ShipQuests_Jalad) == 0) mesq l("- Jalad");
+ if (getq(ShipQuests_QMuller) == 0) mesq l("- Q'Muller");
+ if (getq(ShipQuests_Tibbo) == 0) mesq l("- Tibbo");
+
+ close;
+
+L_Couwan:
+ mes "";
+ mesn;
+ mesq l("What?! This tritan is the worse shirker I ever met!");
+ next;
+ mesq l("Well, thanks for the box. But... He was supposed to bring it back to me himself. I never asked him to give it to you!");
+ next;
+ mesq l("Take these coins in exchange and be careful.");
+ next;
+ mesq l("Not everybody has a kind mind. Scammers can be anywhere, even among us!");
+ next;
+ mesq l("May this be a lesson for you.");
+
+ if (countitem(FishBox) > 0) delitem FishBox, 1;
+ setq ShipQuests_Couwan, 2;
+ Zeny = Zeny + 10;
+ getexp 40, 0;
+ message strcharinfo(0), l("You receive @@ E!", 10);
+
+ close;
+
+L_Location:
+ mes "";
+ mesn;
+ mesq l("There are 6 sailors who will need your help. They are all around the island.");
+ next;
+ mesq l("I can't really help you find them since I've been checking the... Hmm... Landscape, since morning...");
+ next;
+ mesq l("You can try talking with some other sailors to get some information about that.");
+ next;
+
+ .@r = rand(3000)/1000;
+ if (.@r == 1) goto L_Silvio;
+ if (.@r == 2) goto L_Lean;
+
+ setcamnpc "Sapartan";
+ mesq l("Maxe and Sapartan for example?");
+ next;
+
+ restorecam;
+ close;
+
+L_Silvio:
+ setcamnpc "Silvio";
+ mesq l("Silvio for example?");
+ next;
+
+ restorecam;
+ close;
+
+L_Lean:
+ setcamnpc "Lean";
+ mesq l("Lean for example?");
+ next;
+
+ restorecam;
+ close;
+
+L_TaskDone:
+ if (countitem(AquadaBox) == 2) delitem AquadaBox, 2;
+ if (countitem(CroconutBox) == 2) delitem CroconutBox, 2;
+ if (countitem(PlushroomBox) == 2) delitem PlushroomBox, 2;
+ if (countitem(AquadaBox) == 1) delitem AquadaBox, 1;
+ if (countitem(CroconutBox) == 1) delitem CroconutBox, 1;
+ if (countitem(PlushroomBox) == 1) delitem PlushroomBox, 1;
+ setq ShipQuests_Gugli, 2;
+
+ Zeny = Zeny + 250;
+ getexp 50, 0;
+
+ mes "";
+ mesn;
+ mesq l("Well done! The ship is now ready to sail again!");
+ next;
+ mesq l("You should inform Nard of the progress made in loading food and supplies on to the boat. He will be pleased to hear that good news!");
+
+ close;
+
+L_TaskCompleted:
+ mesq l("You are now part of the crew... At least for us down here!");
+ next;
+ mesq l("You should inform Nard of the progress made in loading food and supplies on to the boat. He will be pleased to hear that good news!");
+ next;
+ mesq l("Tell him that everything went fine and that we're almost done with the requisitions.");
+ next;
+
+ goto L_Menu;
+
+L_AllComplete:
+ mesq l("Elmo told me what Nard said, congrats!");
+ next;
+ mesq lg("You're one of us now, that's great! I was sure that you were a kind lady when I first saw you!", "You're one of us now, that's great! I was sure that you were a good man when I first saw you!");
+ next;
+
+ goto L_Menu;
+
+L_Quit:
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
+
+000-1,83,107,0 script GugliBarrierCheck NPC_HIDDEN,2,0,{
+ .@gugli = getq(ShipQuests_Gugli);
+ if (.@gugli > 0) close;
+ doevent "Gugli::OnTalk";
+ close;
+}
diff --git a/npc/000-1/gulukan.txt b/npc/000-1/gulukan.txt
new file mode 100644
index 000000000..7b277fdf6
--- /dev/null
+++ b/npc/000-1/gulukan.txt
@@ -0,0 +1,170 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Reid
+// Description:
+// Sailor part of the Gugli's quest.
+// Croconut box.
+
+000-1,54,90,0 script Gulukan NPC_TRITAN_MAN_SAILOR2,{
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+ .@g = getq(ShipQuests_Gugli);
+ if (.@g == 0) goto L_NoTask;
+
+ .@q = getq(ShipQuests_Gulukan);
+ if (.@q == 1) goto L_Func;
+
+ mesn;
+ mesq l("Yeye @@!", strcharinfo(0));
+ next;
+ mesq l("How are you feeling, now that you walk on steady land? Yeye better?");
+ next;
+
+ menu
+ l("Wow, it seems everyone knows my name!"), -,
+ l("Well, it's not bad to finally feel something beneath my feet."), L_Continue,
+ l("Not so good actually... I would feel better on Nard's ship."), L_Quit;
+
+L_Name:
+ mes "";
+ mesn;
+ mesq l("You know, yeyes love to chat while working.");
+ next;
+
+goto L_Continue2;
+
+L_Continue:
+ mes "";
+ mesn;
+
+L_Continue2:
+ mesq lg("Are you yaying here to explore the island?");
+ next;
+
+ menu
+ lg("Actually Gugli asked me if I would help you bring him some of your boxes."), -,
+ l("Yes, indeed. I prefer to explore places I have never been to, before doing anything else."), L_Quit;
+
+ mes "";
+ mesn;
+ mesq l("Gugli? Oh I see. Yes, Gugli yeye pretty used to shout orders to everybody down here.");
+ next;
+ mesq l("Anyway I am glad I can give you some of these yoyoxs.");
+ next;
+
+ inventoryplace CroconutBox, 1;
+
+ setq ShipQuests_Gulukan, 1;
+ getitem CroconutBox, 1;
+
+ mes "";
+ mesn;
+ mesq lg("Thank you my friend.");
+
+ close;
+
+L_Func:
+ mesn;
+
+ .@q = rand(0, 400) / 100;
+ if (.@q == 0) goto L_RandomA;
+ if (.@q == 1) goto L_RandomB;
+ if (.@q > 1) goto L_RandomC;
+
+L_RandomA:
+ mesq l("Hey.");
+ next;
+ mesq l("What did Gugli yayaid about the box? Was it ok?");
+ next;
+
+ menu
+ l("It's ok."), L_Fine,
+ l("He needs more food."), -;
+
+ mes "";
+ mesn;
+ mesq lg("Yeye sure? I'll yaye some more food in the next box then.");
+
+ close;
+
+L_Fine:
+ mes "";
+ mesn;
+ mesq l("Alright! Yoyone more box and it'll be good.");
+
+ close;
+
+L_RandomB:
+ mesq l("Thanks for the help!");
+ next;
+ mesq l("These yeye boxes are way too heavy to be carried alone onto the ship.");
+
+ close;
+
+L_RandomC:
+ mesq l("I think that yeye's soon be done. Yeye'll soon have a full box of @@s!", getitemlink(CrocClaw));
+ next;
+ mesq l("And you? How's it yaying on your side?");
+ next;
+
+ menu
+ rif(getq(ShipQuests_Gugli) > 1, l("Task is done.")), L_TaskDone,
+ rif(getq(ShipQuests_Gulukan) == 1 && (getq(ShipQuests_Ale) == 0 || getq(ShipQuests_Astapolos) == 0 || getq(ShipQuests_Jalad) == 0 || getq(ShipQuests_QMuller) == 0 || getq(ShipQuests_Tibbo) == 0), l("I'm still busy, I need to find the other sailors.")), -;
+
+ mes "";
+ mesn;
+ mesq l("Who are yeye looking for?");
+ next;
+
+ menu
+ rif(getq(ShipQuests_Ale) == 0, l("Ale.")), L_Top,
+ rif(getq(ShipQuests_Astapolos) == 0, l("Astapolos.")), L_Top,
+ rif(getq(ShipQuests_Jalad) == 0, l("Jalad.")), L_Top,
+ rif(getq(ShipQuests_QMuller) == 0, l("Q'Muller.")), L_Top,
+ rif(getq(ShipQuests_Tibbo) == 0, l("Tibbo.")), L_Bottom,
+ l("Nobody."), L_Quit;
+
+L_Bottom:
+ mes "";
+ mesn;
+ mesq l("Yeye seen this yoiis at the bottom of the island, check around.");
+
+ close;
+
+L_Top:
+ mes "";
+ mesn;
+ mesq l("Yeye seen this yoiis at the top of the island.");
+ next;
+ mesq l("You yoiis should walk to the north.");
+
+ close;
+
+L_NoTask:
+ mes "";
+ mesn;
+ mesq l("*Uff*... And another box of @@s for our starving colleagues is ready.", getitemlink(Croconut));
+
+ close;
+
+L_TaskDone:
+ mes "";
+ mesn;
+ mesq lg("That's perfect, yoiis.");
+
+ close;
+
+L_Quit:
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/jalad.txt b/npc/000-1/jalad.txt
new file mode 100644
index 000000000..74de7f8f4
--- /dev/null
+++ b/npc/000-1/jalad.txt
@@ -0,0 +1,131 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Reid
+// Description:
+// Sailor part of the Gugli quest.
+// Plushroom box.
+
+000-1,46,35,0 script Jalad NPC_ELVEN_MAN_TRADER_SITTING,{
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+ .@g = getq(ShipQuests_Gugli);
+ if (.@g == 0) goto L_NoTask;
+
+ .@q = getq(ShipQuests_Jalad);
+ if (.@q == 1) goto L_CallFunc;
+
+ mesn;
+ mesq l("*Uff*, *Argh*, why don't you give me some help?");
+ next;
+ mesq l("I'm not suited for this kind of work!");
+ next;
+
+ menu
+ l("I was going to ask you if you would need any help."), L_Continue,
+ l("What exactly is your real job?"), -;
+
+ mes "";
+ mesn;
+ mesq l("I'm the cook's assistant of the ship. I help Gado, La Johanne's Chef, in his daily work.");
+ next;
+ mesq l("You should go see him. He is one of the most experienced sailors we have.");
+ next;
+
+ select
+ l("I will surely visit him. Do you need any help with your boxes?");
+
+L_Continue:
+ mes "";
+ mesn;
+ mesq l("Surely. Take this box full of @@s.", getitemlink(Plushroom));
+ next;
+
+ inventoryplace PlushroomBox, 1;
+
+ setq ShipQuests_Jalad, 1;
+ getitem PlushroomBox, 1;
+
+ mes "";
+ mesn;
+ mesq l("They are so tasty when cooked with some @@. Don't drop any of them!", getitemlink(PiouLegs));
+
+ goto L_Close;
+
+L_CallFunc:
+ sailorfood;
+
+ menu
+ rif(getq(ShipQuests_Gugli) > 1, l("Task is done.")), L_TaskDone,
+ rif(getq(ShipQuests_Jalad) == 1 && (getq(ShipQuests_Ale) == 0 || getq(ShipQuests_Astapolos) == 0 || getq(ShipQuests_Gulukan) == 0 || getq(ShipQuests_QMuller) == 0 || getq(ShipQuests_Tibbo) == 0), l("I'm still busy, I need to find the other sailors.")), -,
+ l("What's that?"), L_Plushroom;
+
+ mes "";
+ mesn;
+ mesq l("Who are you looking for?");
+ next;
+
+ menu
+ rif(getq(ShipQuests_Ale) == 0, l("Ale.")), L_Ale,
+ rif(getq(ShipQuests_Astapolos) == 0, l("Astapolos.")), L_Bottom,
+ rif(getq(ShipQuests_Gulukan) == 0, l("Gulukan.")), L_Bottom,
+ rif(getq(ShipQuests_QMuller) == 0, l("Q'Muller.")), L_Bottom,
+ rif(getq(ShipQuests_Tibbo) == 0, l("Tibbo.")), L_Bottom,
+ l("Nobody."), -;
+
+ closedialog;
+ close;
+
+L_Bottom:
+ mes "";
+ mesn;
+ mesq l("I've seen him at the bottom of the island, have a look around.");
+
+ close;
+
+L_Ale:
+ setcamnpc "Ale";
+
+ next;
+ mesn;
+ mesq l("Look, there he is!");
+ next;
+
+ restorecam;
+ close;
+
+L_Plushroom:
+ mes "";
+ mesn;
+ mesq l("'That', as you call it, is a @@. There are plenty on this island!", getitemlink(Plushroom));
+ next;
+ mesq l("It's a kind of mushroom. We call it like that because of it's taste, just like a marshmallow. It also has this name because of it's appearance. It looks like a plush!");
+ next;
+ mesq l("There are some groups of these @@s all around this island. Just pick some and have a try.", getitemlink(Plushroom));
+
+ close;
+
+L_NoTask:
+ mes "";
+ mesn;
+ mesq l("Sometimes, I wish someone would be sent here to help us.");
+
+ close;
+
+L_TaskDone:
+ mes "";
+ mesn;
+ mesq l("Perfect!");
+
+L_Close:
+ goodbye;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/lean.txt b/npc/000-1/lean.txt
new file mode 100644
index 000000000..93cfeb7fa
--- /dev/null
+++ b/npc/000-1/lean.txt
@@ -0,0 +1,74 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Reid
+// Description:
+// Sailor who gives some informations to the player.
+
+000-1,79,108,0 script Lean NPC_ELVEN_MAN_BLONDE,{
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+ .@gugli = getq(ShipQuests_Gugli);
+
+ mesn;
+ mesq l("Hi! I can finally see you under the sunlight!");
+ next;
+ mesq l("I hope you don't mind that we used your raft to build this ramp.");
+ next;
+ mesq l("We usually don't stop in such splendid places, but the captain let us stay here while he writes down the location of this new island on his map!");
+ next;
+ mesq l("Some of the crew are looking for goods we can trade with at our next destination.");
+ next;
+
+ menu
+ rif(.@gugli == 1, l("Well, I was in fact looking for them. Where are they now?")), L_Sailors,
+ l("Wait... Where are we going?"), L_Artis;
+
+L_Artis:
+ mes "";
+ mesn;
+ mesq l("Artis of course!");
+ next;
+ mesq l("It's where every merchant ship end their road and we won't be an exception.");
+ next;
+ mesq l("If you're looking for us there, most of us will be at the tavern of the Red Plush, at the bar counter, for Silvio's case...");
+
+ goto L_Close;
+
+L_Sailors:
+ mes "";
+ mesn;
+ mesq l("They are all around the island.");
+ next;
+ mesq l("I'm sure Tibbo is alone in the south-west corner of the island. He believes it's the best place to collect @@s.", getitemlink(Aquada));
+ next;
+ mesq l("While Jalad and Ale like to work together, as they usually do on the ship, last time I've seen them, they were near the big lake, north from here.");
+ next;
+ mesq l("They shouldn't be too far from each other.");
+ next;
+
+ menu
+ l("Thank you for your help."), L_Close,
+ l("Gugli mentioned six sailors. What about the others?"), -;
+
+ mes "";
+ mesn;
+ mesq l("I'm not sure. They probably left the ship early this morning. I was not awake yet.");
+ next;
+ mesq l("You should ask Maxe. He's an early riser.");
+
+ close;
+
+L_Close:
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/mapflags.txt b/npc/000-1/mapflags.txt
new file mode 100644
index 000000000..708dd2ab8
--- /dev/null
+++ b/npc/000-1/mapflags.txt
@@ -0,0 +1 @@
+000-1 mapflag town
diff --git a/npc/000-1/maxe.txt b/npc/000-1/maxe.txt
new file mode 100644
index 000000000..8bc3eeb17
--- /dev/null
+++ b/npc/000-1/maxe.txt
@@ -0,0 +1,112 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Reid
+// Description:
+// Friend of Sapartan, he gives some information on how to find Gulukan, Astapolos and Q-Muller.
+
+000-1,72,110,0 script Maxe NPC_DEMON_MAN_SITTING_UNDER_TREE,{
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+ .@gugli = getq(ShipQuests_Gugli);
+ .@knife = getq(ShipQuests_Knife);
+
+ mesn;
+ mesq lg("We are glad captain Nard has let you join us down here!");
+ next;
+ mesq l("Living inside a ship is great, but we sometimes need some fresh air.");
+ next;
+ mesq l("Anyway, can I help you in any way?");
+ next;
+
+ menu
+ rif(.@gugli == 0, l("Well, is there anything I can do here to help?")), L_Help,
+ rif(.@gugli == 1, lg("Gugli asked me to help the sailors to gather food. Do you know where I can find them?")), L_Sailors,
+ rif(.@gugli > 1, l("Seems I've helped everyone here. I don't know what to do now!")), L_Annoyed,
+ rif(.@knife == 0, l("It looks like you are an expert of the life inside 'La Johanne'. Do you know any hidden secrets nobody knows?")), L_Secrets,
+ l("No thanks, not at the moment."), L_Quit;
+
+L_Help:
+ mes "";
+ mesn;
+ mesq l("You could start by talking to Gugli. He always has tasks for people willing to help!");
+
+ close;
+
+L_Sailors:
+ mes "";
+ mesn;
+ mesq l("I remember I saw a few of them leaving the ship early this morning to get a head start on today's work.");
+ next;
+ mesq l("I recall seeing Gulukan, Astapolos and Q'Muller.");
+ next;
+
+ goto L_MenuSailors;
+
+L_MenuSailors:
+ menu
+ l("Do you know where can I find Gulukan?"), L_Gulukan,
+ l("Any clue on where Astapolos may be hidden?"), L_Astapolos,
+ l("What about Q'Muller? Where is he?"), L_Qmuller,
+ l("Alright. I will go looking for them now."), L_Quit;
+
+L_Gulukan:
+ mes "";
+ mesn;
+ mesq l("Oh, he is not far away from here. Just take the road through the crocojungle north from here.");
+ next;
+ mesq l("You will find a wooden sign near a crossroad. He is a few steps on the left.");
+ next;
+
+ goto L_MenuSailors;
+
+L_Astapolos:
+ mes "";
+ mesn;
+ mesq l("Astapolos... That guy is shy like a piou!");
+ next;
+ mesq l("He likes to hide near the little lake in the north-west side of the island.");
+ next;
+
+ goto L_MenuSailors;
+
+L_Qmuller:
+ mes "";
+ mesn;
+ mesq l("You need to cross the crocojungle heading north.");
+ next;
+ mesq l("You can spot Q'Muller on a cliff off toward the west, busy collecting @@s.", getitemlink(Plushroom));
+ next;
+
+ goto L_MenuSailors;
+
+L_Annoyed:
+ mes "";
+ mesn;
+ mesq l("There is always something you can do here, like killing some tortugas or helping Peter clean the ship from rattos.");
+
+ close;
+
+L_Secrets:
+ mes "";
+ mesn;
+ mesq l("Nope, there are no secrets hidden within the ship's hull. Some sailors swear they have seen stowaways hidden somewhere. The bow or the stern? Just stories sailors love to tell...");
+ next;
+ mesq l("Oh! And in one of the rooms of the second deck you can find Gado's knives. Our chef keeps there the sharpest ones... Probably not just to cut some carrots...");
+ next;
+ mesq l("Go and grab one of them. A good knife will help with your hunting the creatures of this island.");
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+
+L_Quit:
+ goodbye;
+}
diff --git a/npc/000-1/muller.txt b/npc/000-1/muller.txt
new file mode 100644
index 000000000..276557cb3
--- /dev/null
+++ b/npc/000-1/muller.txt
@@ -0,0 +1,132 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Reid
+// Description:
+// Sailor part of the Gugli's quest.
+// Plushroom box.
+
+000-1,35,69,0 script Q'Muller NPC_ORC_MAN,{
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+ .@g = getq(ShipQuests_Gugli);
+ if (.@g == 0) goto L_NoTask;
+
+ .@q = getq(ShipQuests_QMuller);
+ if (.@q == 1) goto L_CallFunc;
+
+ mesn;
+ mesq l("Can't you see I'm working?!");
+ next;
+
+ select
+ l("Well I'm working too! Don't you want me to carry one of these boxes back to Gugli?");
+
+ mes "";
+ mesn;
+ mesq l("Oh I see... Sailors are not able to do their job anymore, is it like that?!");
+ next;
+
+ menu
+ l("Indeed! Goodbye."), L_Quit,
+ l("Yes, it is true! You are not able at all. Nard has been waiting for the food for too long already. Hurry up, you lazy sailors!"), -;
+
+ mes "";
+ mesn;
+ mesq l("Are you blind? Do you really think these boxes are light and soft as a piou's feather?!");
+ next;
+
+ select
+ lg("I am sure that I can run with one of them on my shoulder.");
+
+ mes "";
+ mesn;
+ mesq l("Well then... Take this one!");
+ next;
+
+ inventoryplace PlushroomBox, 1;
+
+ setq ShipQuests_QMuller, 1;
+ getitem PlushroomBox, 1;
+
+ mes "";
+ mesn;
+ mesq l("And now I want to see you run!");
+
+ close;
+
+L_CallFunc:
+ sailorfood;
+
+ menu
+ rif(getq(ShipQuests_Gugli) > 1, l("Task is done.")), L_TaskDone,
+ rif(getq(ShipQuests_QMuller) == 1 && (getq(ShipQuests_Ale) == 0 || getq(ShipQuests_Astapolos) == 0 || getq(ShipQuests_Gulukan) == 0 || getq(ShipQuests_Jalad) == 0 || getq(ShipQuests_Tibbo) == 0), l("I'm still busy, I need to find the other sailors.")), -,
+ l("What's that?"), L_Plushroom;
+
+ mes "";
+ mesn;
+ mesq l("Who are you looking for?");
+ next;
+
+ menu
+ rif(getq(ShipQuests_Ale) == 0, l("Ale.")), L_Top,
+ rif(getq(ShipQuests_Astapolos) == 0, l("Astapolos.")), L_Top,
+ rif(getq(ShipQuests_Jalad) == 0, l("Jalad.")), L_Top,
+ rif(getq(ShipQuests_Gulukan) == 0, l("Gulukan.")), L_Bottom,
+ rif(getq(ShipQuests_Tibbo) == 0, l("Tibbo.")), L_Bottom,
+ l("Nobody."), L_Quit;
+
+L_Bottom:
+ mes "";
+ mesn;
+ mesq l("I've seen him at the bottom of the island, check around.");
+
+ close;
+
+L_Top:
+ mes "";
+ mesn;
+ mesq l("I've seen him at the top of the island.");
+ next;
+ mesq l("You should walk to the north.");
+
+ close;
+
+L_Plushroom:
+ mes "";
+ mesn;
+ mesq l("'That', as you call it, is a @@. There are plenty on this island!", getitemlink(Plushroom));
+ next;
+ mesq l("It's a kind of mushroom. We call it like that because of it's taste, just like a marshmallow. It also has this name because of it's appearance, it looks like a plush!");
+ next;
+ mesq l("There are few groups of these @@s all around this island. Just pick some and have a try.", getitemlink(Plushroom));
+
+ close;
+
+L_NoTask:
+ mes "";
+ mesn;
+ mesq l("You see? I'm working here!");
+
+ close;
+
+L_TaskDone:
+ mes "";
+ mesn;
+ mesq l("Good to hear!");
+ next;
+
+ goodbye;
+
+L_Quit:
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/panels.txt b/npc/000-1/panels.txt
new file mode 100644
index 000000000..71097fa3c
--- /dev/null
+++ b/npc/000-1/panels.txt
@@ -0,0 +1,54 @@
+// Evol scripts.
+// Authors:
+// Alige
+// Qwerty Dragon
+// Description:
+// Panels to give advice to the players.
+
+000-1,65,93,0 script #panel1 NPC_NO_SPRITE,{
+ mesn "Narrator";
+ mes col(l("Your heart quickens as your gaze focuses upon a small wooden panel, partly obscured under a layer of wind-blown sand."), 9);
+ next;
+ mes col(l("You wipe off enough of the sand to manage to read the message written on this crude piece of wood."), 9);
+ next;
+ mesq l("It's a dangerous place out here. Beware of the mischievous creatures living here!");
+ next;
+ mesq l("Not content to stay buried in their burrows in the sand, Crocs can be quite a nuisance, infesting this whole island. Tender Feet and Newbies are advised: Avoid touching these crawling red devils. They have huge, deadly claws that can make mincemeat of you! You can recognize them easily by their crabby personalities. Be careful younglings.");
+ next;
+ mesq l("Furthermore, unless you are planning to stick it out, you should also not even think about gaining experience by messing with those icky pink land jellies. The pink could stick on you, imagine the horror!");
+ next;
+ mesq l("In fact... Oh, the things that I could tell... But ran out of space on this... Just be reasonable and go home.");
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
+
+000-1,89,51,0 script #panel2 NPC_NO_SPRITE,{
+ mesn "Narrator";
+ mes col(l("This panel looks in rather good shape, as though some people take care of it regularly. Maybe it has important information."), 9);
+ next;
+ mes col(l("You can read some lines that are nicely carved into the soft wooden planks."), 9);
+ next;
+ mesq l("The further you go, the more experience you will get, so here's a small description of all the stats you can upgrade with time. But note that these will probably change in the future and have more complex effects.");
+ next;
+ mesq l("Strength multiplies the damage of your hits, especially melee ones. You will also be able to carry heavier stuff.");
+ next;
+ mesq l("Agility greatly increases your attack speed and the chances of you dodging enemy hits.");
+ next;
+ mesq l("Vitality raises your maximum health points and defense.");
+ next;
+ mesq l("Intelligence raises your maximum mana points (good for mages) and your mind abilities. Please note: Magic system has not yet been implemented in this world.");
+ next;
+ mesq l("Dexterity increases your bow damage and your accuracy.");
+ next;
+ mesq l("Luck helps you do critical hits and dodge the ones dealt by enemies.");
+ next;
+ mesq l("Have fun, but always remember to pick your stats with good care.");
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/sapartan.txt b/npc/000-1/sapartan.txt
new file mode 100644
index 000000000..16da0eb9d
--- /dev/null
+++ b/npc/000-1/sapartan.txt
@@ -0,0 +1,102 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Description:
+// Friend of Maxe, he gives some information on combat system.
+
+000-1,74,111,0 script Sapartan NPC_SAPARTAN,{
+ mesn;
+ mesq l("Hey Maxe, it's @@!", strcharinfo(0));
+ next;
+
+ setcamnpc "Maxe";
+ mesn "Maxe";
+ mesq lg("@@? Welcome my dear!", "@@? Welcome my dear!", strcharinfo(0));
+ next;
+ mesq lg("Last time I saw you, you were lost at sea on your raft.");
+ next;
+ restorecam;
+
+ mesn;
+ mesq lg("True but now she seems pretty fine! Am I right?", "True but now he seems pretty fine! Am I right?");
+ next;
+
+ menu
+ l("Thank you, sir, for your kind words. I am feeling better now."), -,
+ lg("I'm still a bit weak at the moment. We should probably talk later."), L_Quit;
+
+ mes "";
+ mesn;
+ mesq l("You can now stay with your new friends and enjoy the warm sand of this little island.");
+ next;
+ mesq l("But remember that not every place in this world is peaceful and safe nowadays. Even the white shores you are walking on can hide some dangerous beings.");
+ next;
+
+ select
+ l("What danger?! Where?!");
+
+ setcamnpc "Maxe";
+ mes "";
+ mesn "Maxe";
+ mesq lg("Come on, Sap! You are scaring her with your stories.", "Come on, Sap! You are scaring him with your stories.");
+ next;
+ mesq lg("I'm sure she will soon be able to fight all of the creatures living here without any problem.", "I'm sure he will soon be able to fight all of the creatures living here without any problem.");
+ next;
+
+ restorecam;
+
+ mes "";
+ mesn;
+ mesq lg("Maybe... But I prefer having well-trained people around me when it comes to fighting against dangerous creatures. Do you already feel adept fighting enemies?");
+ next;
+
+ menu
+ l("No, I don't, but I would like to know more about that."), -,
+ l("Well... I've only killed some little pious in the ship, that's all."), -,
+ l("Yes, I feel strong enough for dangerous combats!"), L_Quit;
+
+ mes "";
+ mesn;
+ mesq l("Then I can give you some tips about fighting.");
+ next;
+ mesq l("The first thing you should do is to evaluate your enemy.");
+ next;
+ mesq l("You can easily see if a monster is easy to kill or just impossible to defeat. Do not try against creatures that are way more powerful than you... You'd be risking your life for nothing.");
+ next;
+ mesq l("Secondly, choose wisely which weapon is suited for you. Some people like to face their enemies closely with a heavy axe, others prefer to attack from a distance with a bow for example.");
+ next;
+
+ select
+ l("Yeah, well what's the difference?");
+
+ mes "";
+ mesn;
+ mesq l("On one hand, ranged weapons are generally weaker than melee ones, but you attack from a safer position. On the other hand, depending on the level of the weapon, melee ones potentially can yeild quicker kills.");
+ next;
+ mesq l("After choosing your weapon, you also need to know how to use it.");
+ next;
+ mesq l("You can attack a monster by clicking directly on it. Once selected, you may notice a bar near your target showing you how much health it has left.");
+ next;
+ mesq l("You can also attack an enemy from your keyboard pressing the 'A' key to select it, and the 'Ctrl' key to attack it, this of course works if you didn't change your keyboard keys yet.");
+ next;
+
+ menu
+ l("Thank you for your tricks. I am going to try them now!"), -,
+ l("I already know everything. Bye."), L_Quit;
+
+ mes "";
+ mesn;
+ mesq l("You're welcome. If you can't remember something, just come back here!");
+ next;
+
+ goodbye;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+
+L_Quit:
+ goodbye;
+}
diff --git a/npc/000-1/shop.txt b/npc/000-1/shop.txt
new file mode 100644
index 000000000..44b3479ac
--- /dev/null
+++ b/npc/000-1/shop.txt
@@ -0,0 +1,33 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Fexil's shop bag.
+
+000-1,84,98,0 trader Bag#000-1 NPC_SHOP_BAG,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem PiouLegs, -1, 15;
+ sellitem Bread, -1, 15;
+ sellitem Croconut, -1, 50;
+ sellitem Aquada, -1, 50;
+ sellitem Armbands, -1, 20;
+ sellitem LousyMoccasins, -1, 20;
+ sellitem PiouSlayer, -1, 15;
+
+ .sex = G_OTHER;
+ .distance = 3;
+ end;
+
+OnClock0000:
+ restoreshopitem PiouLegs, 15;
+ restoreshopitem Bread, 15;
+ restoreshopitem Croconut, 50;
+ restoreshopitem Aquada, 50;
+ restoreshopitem Armbands, 20;
+ restoreshopitem LousyMoccasins, 20;
+ restoreshopitem PiouSlayer, 15;
+}
diff --git a/npc/000-1/silvio.txt b/npc/000-1/silvio.txt
new file mode 100644
index 000000000..7cc3c32b2
--- /dev/null
+++ b/npc/000-1/silvio.txt
@@ -0,0 +1,186 @@
+// Evol scripts.
+// Authors:
+// Qwerty Dragon
+// Reid
+// Description:
+// Perverted and arrogant sailor.
+
+000-1,86,99,0 script Silvio NPC_SILVIO,{
+ mesn;
+ mesq l("Hey!");
+ next;
+ mesq lg("How are you doing, cutie?", "How are you doing, dude?");
+ next;
+
+ menu
+ l("Hello... Do I know you?"), -,
+ rif(getq(ShipQuests_Gugli) > 0 && getq(General_Narrator) == 0, l("Fine, could you please tell me where I can find Gugli's sailors?")), L_Sailors,
+ l("Uhm, bye."), L_Quit;
+
+ mes "";
+ mesn;
+ mesq lg("Hehe, no. But I'm sure a fox like you would love to meet a catch like me!", "Hehe, no. But I'm sure a noob like you would like to meet an idol like me.");
+ next;
+ mesq lg("So, what good wind brought you here? Were you on your raft to meet me? Or is it because you've heard of my feats in Artis?", "So, what good wind brought you here? Were you on your raft to meet my Julia? Or is it because you wanted to see the beautiful waitresses of Artis?");
+ next;
+
+ menu
+ lg("You're right, it's about you.", "You're right, it's about Julia."), L_Julia,
+ l("What is Artis?"), L_Artis,
+ l("None of them?"), -;
+
+ mes "";
+ mesn;
+ mesq lg("My beauty. I was not always a sailor, you know, I was once an important individual!", "My friend. I was not always a sailor, you know, I was once an important individual!");
+ next;
+ mesq l("Before...");
+ next;
+
+ setcamnpc "Gugli";
+ mes "";
+ mesn "Gugli";
+ mesq l("Hey, don't worry about him, it's one of the first days in a long time that we can just chill out.");
+ next;
+ mesq l("Maybe he over did it with the bottle today to celebrate that!");
+ next;
+ restorecam;
+
+ menu
+ l("He's funny, it's not a problem."), -,
+ l("Ok, I will leave him alone."), L_ForeverAlone;
+
+ setcamnpc "Gugli";
+ mes "";
+ mesn "Gugli";
+ mesq l("Oh alright, nevermind then.");
+ next;
+ restorecam;
+
+ mesn;
+ mesq l("Ah... Gugli... He's too young to understand our conversation.");
+ next;
+ mesq l("So, what was I saying?");
+ next;
+
+ menu
+ l("You told me that you 'were' important."), L_VeryImportantNoob,
+ l("You mentioned the quality of your wine."), -;
+
+ mes "";
+ mesn;
+ mesq l("Oh really? How could I forget something as important as that?!");
+ next;
+ mesq l("I think that my wine is of great quality! I'm on my second bottle and I already... What were we talking about again?");
+
+ close;
+
+L_VeryImportantNoob:
+ mes "";
+ mesn;
+ mesq l("It's true!");
+ next;
+ mesq l("But I can't tell you anything about it, I'm sorry.") ;
+ next;
+
+ setcamnpc "Gugli";
+ mes "";
+ mesn "Gugli";
+ mesq l("Hey Silvio, it's your turn to carry the package, go!");
+ next;
+ restorecam;
+
+ mesn;
+ mesq lg("Duty calls me, *hic*, see you later, honey.", "Duty calls me, *hic*, see you later, dude.");
+
+ close;
+
+L_Julia:
+ mes "";
+ mesn;
+ mesq lg("You honor me, my beauty, but I'm already taken by Julia!", "Not to kill your dream, but... Julia is mine!");
+ next;
+ mesq l("She said she will accept me when pious will have teeth. It's just a matter of time, you see?");
+ next;
+
+ menu
+ l("I see. Bye!"), L_Quit,
+ l("Oh look, there's a piou behind you!"), L_Piou;
+
+L_Piou:
+ mes "";
+ mesn;
+ mesq l("Seriously?!");
+ next;
+ mesq l("Hurry, hurry! We need to check its teeth!");
+
+ close;
+
+L_Artis:
+ mes "";
+ mesn;
+ mesq l("Artis is a very nice place. There are some hot chicks...");
+ next;
+ mesq l("The Raijin from the library flirted with me a while ago, so has Enora from the Legion.");
+ next;
+ mesq l("Oh, and Olga from the marketplace as well!");
+ next;
+ mesq l("You should look for them when we arrive at the port. You won't regret it! Ehehe...");
+
+ goodbye;
+
+L_ForeverAlone:
+ mes "";
+ mesn "Narrator";
+ mes col(l("Silvio starts to speak to his bottle, you leave, letting him have a private conversation."), 9);
+
+ close;
+
+L_Sailors:
+ mes "";
+ mesn;
+ mesq l("What? Why? They aren't more attractive than me, why do you want to see them?");
+ next;
+ mesq l("And what would you give me in exchange for that information?");
+ next;
+
+ setcamnpc "Gugli";
+ mes "";
+ mesn "Gugli";
+ mesq lg("Stop heckling her, Silvio, or I'll tell her how you always cry like a little baby during thunderstorms.", "Stop heckling him, Silvio, or I'll tell him how you always cry like a little baby during thunderstorms.");
+ next;
+ restorecam;
+
+ mesn;
+ mesq l("I...");
+ next;
+ mesq l("How could you... We said we wouldn't talk about that again!");
+ next;
+ mesq l("Tibbo went to the south-east of the island, others are gone to the north, and I think that Gulukan is not so far from here.");
+ next;
+ mesq l("But anyway, take the road which goes to the north to find everybody.");
+ next;
+ mesq l("Now, leave me alone...");
+ next;
+
+ menu
+ l("See you."), L_Quit,
+ l("*Imitate a thunder's sound.*"), -;
+
+ closedialog;
+
+ npctalk3 l("Aaaaaahhhhhh!");
+
+ close;
+
+L_Quit:
+ closedialog;
+
+ npctalk3 l("Give me a kiss before you say goodbye!");
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/tarlan.txt b/npc/000-1/tarlan.txt
new file mode 100644
index 000000000..579144788
--- /dev/null
+++ b/npc/000-1/tarlan.txt
@@ -0,0 +1,65 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Sailor hitting a crocotree, then being struck by a falling croconut.
+
+000-1,33,37,0 script Tarlan NPC_TARLAN,{
+ .dir = 2;
+
+ mesn;
+ .@a = rand(4);
+ if (.@a == 0) goto L_HardToHit;
+ if (.@a == 1) goto L_Aouch;
+ if (.@a == 2) goto L_DoYou;
+
+ mesq l("Hey you!");
+ next;
+ mesq l("What are you looking for?");
+ next;
+
+ menu
+ l("Some food."), L_Food,
+ l("Nothing, just hanging around."), -;
+
+ closedialog;
+ npctalk3 l("Ok, see you then!");
+ goto L_Quit;
+
+L_Food:
+ mes " ";
+ mesn;
+ mesq l("You can yaye some @@s by hitting these crocotrees.", getitemlink(Croconut));
+ next;
+ mesq l("Yeye be careful with wild animal's food, some of them are yeyery dangerous, especially the crocs.");
+
+ goto L_Quit;
+
+L_HardToHit:
+ mesq l("These crocotrees are full of yaying @@s, but they are so hard to hit...", getitemlink(Croconut));
+
+ goto L_Quit;
+
+L_Aouch:
+ mesq l("Ayouyouch! My head...");
+ next;
+ mesq l("Damn @@.", getitemlink(Croconut));
+
+ goto L_Quit;
+
+L_DoYou:
+ mesq l("Do you want to try?");
+ next;
+ mesq l("Just hit the trunk, and it will yeye a @@.", getitemlink(Croconut));
+
+ goto L_Quit;
+
+L_Quit:
+ .dir = 4;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-1/tibbo.txt b/npc/000-1/tibbo.txt
new file mode 100644
index 000000000..5e5a2701d
--- /dev/null
+++ b/npc/000-1/tibbo.txt
@@ -0,0 +1,124 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Reid
+// Description:
+// Sailor part of the Gugli's quest.
+// Aquada box.
+
+000-1,34,111,0 script Tibbo NPC_ELVEN_MAN_STANDING,{
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+ .@g = getq(ShipQuests_Gugli);
+ if (.@g == 0) goto L_NoTask;
+
+ .@q = getq(ShipQuests_Tibbo);
+ if (.@q == 1) goto L_CallFunc;
+
+ mesn;
+ mesq l("Uh? Hi! I'm sorry, but I have no time for chatting.");
+ next;
+
+ select
+ l("Fine... I was just going to give you some help...");
+
+ mes "";
+ mesn;
+ mesq l("Hel... What?! Wait!");
+ next;
+ mesq l("What kind of help?");
+ next;
+
+ select
+ lg("Gugli asked me to help you carrying one of these boxes you are filling.");
+
+ mes "";
+ mesn;
+ mesq l("Then it seems I have to apologize.");
+ next;
+ mesq l("I am surprised someone has been sent here to help. It is quite... unusual.");
+ next;
+ mesq l("Bring this box to Gugli. He will be extremely happy!");
+ next;
+
+ inventoryplace AquadaBox, 1;
+
+ setq ShipQuests_Tibbo, 1;
+ getitem AquadaBox, 1;
+
+ mes "";
+ mesn;
+ mesq l("Thank you and be careful with that box. I have worked really hard to fill it!");
+
+ goto L_Close;
+
+L_CallFunc:
+ sailorfood;
+
+ menu
+ rif(getq(ShipQuests_Gugli) > 1, l("Task is done.")), L_TaskDone,
+ rif(getq(ShipQuests_Tibbo) == 1 && (getq(ShipQuests_Ale) == 0 || getq(ShipQuests_Astapolos) == 0 || getq(ShipQuests_Gulukan) == 0 || getq(ShipQuests_Jalad) == 0 || getq(ShipQuests_QMuller) == 0), l("I'm still busy, I need to find the other sailors.")), -,
+ l("What's that food?"), L_Aquada;
+
+ mes "";
+ mesn;
+ mesq l("Who are you looking for?");
+ next;
+
+ menu
+ rif(getq(ShipQuests_Ale) == 0, l("Ale.")), L_Top,
+ rif(getq(ShipQuests_Astapolos) == 0, l("Astapolos.")), L_Top,
+ rif(getq(ShipQuests_Gulukan) == 0, l("Gulukan.")), L_Top,
+ rif(getq(ShipQuests_Jalad) == 0, l("Jalad.")), L_Top,
+ rif(getq(ShipQuests_QMuller) == 0, l("Q'Muller.")), L_Top,
+ l("Nobody."), -;
+
+ goto L_Close;
+
+L_Top:
+ mes "";
+ mesn;
+ mesq l("I've seen him at the top of the island.");
+ next;
+ mesq l("You should walk to the north to find him.");
+
+ close;
+
+L_Aquada:
+ mes "";
+ mesn;
+ mesq l("This is an @@, a light blue sea fruit. They're highly desired in the archipelago.", getitemlink(Aquada));
+ next;
+ mesq l("You can find them in the ocean, near corals and other sea beings. But the sea is too heavy today, you shouldn't try swimming for now.");
+ next;
+ mesq lg("Otherwise, if you really want one, and if you feel capable, you can try killing tortugas or crocs if you're strong enough. I'm sure they could drop one or two @@s.",
+ "Otherwise, if you really want one, and if you feel capable, you can try killing tortugas or crocs if you're strong enough. I'm sure they could drop one or two @@s.", getitemlink(Aquada));
+
+ close;
+
+L_NoTask:
+ mes "";
+ mesn;
+ mesq l("I'm sorry but I have no time to chat with you.");
+
+ close;
+
+L_TaskDone:
+ mes "";
+ mesn;
+ mesq l("Awesome!");
+
+ close;
+
+L_Close:
+ goodbye;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-0/_import.txt b/npc/000-2-0/_import.txt
new file mode 100644
index 000000000..795dcc45d
--- /dev/null
+++ b/npc/000-2-0/_import.txt
@@ -0,0 +1,9 @@
+// Map 000-2-0: First Deck
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/000-2-0/_mobs.txt",
+"npc/000-2-0/_warps.txt",
+"npc/000-2-0/billybons.txt",
+"npc/000-2-0/doors.txt",
+"npc/000-2-0/julia.txt",
+"npc/000-2-0/mapflags.txt",
+"npc/000-2-0/note.txt", \ No newline at end of file
diff --git a/npc/000-2-0/_mobs.txt b/npc/000-2-0/_mobs.txt
new file mode 100644
index 000000000..018c21bf2
--- /dev/null
+++ b/npc/000-2-0/_mobs.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-2-0: Second Deck mobs
+000-2-1,52,32,21,9 monster Piou 1002,3,30000,20000
+000-2-1,52,32,21,9 monster Maggot 1030,2,30000,20000 \ No newline at end of file
diff --git a/npc/000-2-0/_warps.txt b/npc/000-2-0/_warps.txt
new file mode 100644
index 000000000..5496ecaea
--- /dev/null
+++ b/npc/000-2-0/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-2-0: First Deck warps
+000-2-0,31,25,0 warp #000-2-0_31_25 0,0,000-2-1,72,29
diff --git a/npc/000-2-0/billybons.txt b/npc/000-2-0/billybons.txt
new file mode 100644
index 000000000..23e056a89
--- /dev/null
+++ b/npc/000-2-0/billybons.txt
@@ -0,0 +1,96 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Drunk easteregg telling about the player's past.
+
+000-2-0,20,23,0 script Billy Bons NPC_BILLY_BONS,{
+ if (rand(5) == 2) goto L_Hic;
+
+ mesn;
+ mesq l("You? Here?");
+ mesq l("How is *hic* it possible?");
+ next;
+
+ mesn "Narrator";
+ mes col(l("The sailor chugs his beer."), 9);
+ next;
+
+ select
+ lg("Excuse me? Do you know who I am?");
+
+ mes "";
+ mesn;
+ mesq l("Don't do theee... *hic* with me eh!");
+ next;
+
+ menu
+ l("Are you ok?"), L_Quit,
+ l("Alright... Bye."), -;
+
+ mes "";
+ mesn;
+ mesq lg("No and *hic*... No, you and you and your... *burp* stup*hic* guild!");
+ next;
+ mesq l("You tried to get rid of me, eeh? But surprise! I'm still here... *hic* Or there...");
+ next;
+ mesq l("But you won't *hic* me this time...");
+ next;
+
+ menu
+ l("What are you talking about? What guild?"), L_Quit,
+ l("You are full of wine, my friend..."), -,
+ l("You should go and get some sleep."), L_Quit;
+
+ mes "";
+ mesn;
+ mesq l("If I saw *hic* who you were... *hic* Would not have helped you! ");
+ next;
+
+ menu
+ l("But who am I?"), -,
+ l("What am I supposed to say?"), L_Quit,
+ l("You should go and get some sleep."), L_Secret;
+
+ mes "";
+ mesn;
+ mesq l("The giant boogeyman!");
+
+ close;
+
+L_Secret:
+ mes "";
+ mesn;
+ mesq l("Hear me *hic* well, what ever, whatididever you will *hic* said ab... uhm... out what?! You saw there, the Legion of Aemil won't let it get public.");
+ next;
+ mesq l("Nobody will know about the existence of the Mercurians.");
+ next;
+ mesq l("Nobody! *burp*");
+ next;
+
+ close;
+
+L_Hic:
+ npctalk3 l("*Hic*");
+
+ close;
+
+L_Quit:
+ mes "";
+ mesn;
+ mesq l("Yeah you're all like *hic* that in Esperia, but you won't get me! *burp*");
+ next;
+ mesq l("I'm not that numb eeh *hic* what did ever yous disco... ...vered there, the Legion of Aemil won't get me!");
+ mesq l("*burp*");
+ next;
+
+ mesn "Narrator";
+ mes col(l("The sailor turns his back to you."), 9);
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
diff --git a/npc/000-2-0/doors.txt b/npc/000-2-0/doors.txt
new file mode 100644
index 000000000..dd65645c3
--- /dev/null
+++ b/npc/000-2-0/doors.txt
@@ -0,0 +1,85 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Doors NPCs.
+// The third value of the .@nard variable has been removed for the beta2, it'll then be re-added for the Aurora release.
+// Variable:
+// 0 ShipQUests_Nard
+// 1 ShipQuests_Julia
+// Values:
+// Nard:
+// 00 Introduction of the boxes and Nard. This is displayed when the player never spoke to Nard or his box.
+// 01 Nard spoke and gave access to the outdoor of the ship.
+// 02 Completed the Gugli quest.
+// 03 ChefGado Quest accepted.
+// 04 ChefGado Quest completed and "Introduction" chapter finalized.
+// 05 Reward taken from the box.
+// 10 Has not talked to Julia
+// 11 Need to see Julia
+// 12 Has been registered by Julia
+
+000-2-0,19,28,0 script AreaNPC#doors1 NPC_HIDDEN,0,0,{
+
+OnTouch:
+ .@nard = getq(ShipQuests_Nard);
+
+ if (getq(General_Narrator) > 0)
+ {
+ warp "000-1", 93, 100;
+ close;
+ }
+
+ if (.@nard == 4) goto L_GotoNard;
+ if (.@nard == 5) goto L_End;
+ if (.@nard > 0 && countitem(718) > 0) goto L_Key;
+
+ setcamnpc "Julia";
+ mesn "Julia";
+ mesq l("The captain has locked the door, you should go see him.");
+ next;
+
+ mesn "Narrator";
+ mes col(l("Captain Nard is in the room to your right."), 9);
+ next;
+ restorecam;
+
+ close;
+
+L_Key:
+ warp "000-1", 93, 100;
+ close;
+
+L_GotoNard:
+ setcamnpc "Julia";
+ mesn "Julia";
+ mesq l("The captain is waiting for you! Hurry up.");
+ next;
+ restorecam;
+
+ close;
+
+L_End:
+ mesn "Narrator";
+ mesq col(l("This door is locked."), 9);
+ setcamnpc "Julia";
+ next;
+ mesn "Julia";
+ mesq l("We're soon leaving that island, please return to your cabine.");
+ next;
+ restorecam;
+
+ close;
+}
+
+000-2-0,33,28,0 script AreaNPC#doors2 NPC_HIDDEN,0,0,{
+
+OnTouch:
+ .@julia = getq(ShipQuests_Julia);
+ if (.@julia == 2) goto L_Warp;
+ close;
+
+L_Warp:
+ warp "000-2-3", 20, 27;
+ close;
+}
diff --git a/npc/000-2-0/julia.txt b/npc/000-2-0/julia.txt
new file mode 100644
index 000000000..33916d85b
--- /dev/null
+++ b/npc/000-2-0/julia.txt
@@ -0,0 +1,302 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Qwerty Dragon
+// Vasily_Makarov
+// Description:
+// Allows to change language and talks about what happened to him.
+// 2 Bits Array:
+// ShipQuests
+// Variables:
+// 0 ShipQuests_Julia
+// 1 ShipQuests_ChefGado
+// 2 ShipQuests_Nard
+// Values:
+// Julia:
+// 10 Default, no quest given.
+// 01 Need to see Julia.
+// 02 Has been registered by Julia.
+// Gado:
+// 10 Default, no quest given.
+// 11 Quest accepted.
+// 12 Ingredients collected, ready to poison Julia.
+// 13 Julia poisoned.
+// 14 Quest complete. Chef Gago wins.
+// 15 Quest complete. Julia wins (poison dish returned).
+// 16 Quest complete. Julia wins.
+// Nard:
+// 20 Introduction of the boxes and Nard. This is displayed when the player never spoke to Nard or his box.
+// 21 Nard spoke and gave access to the outdoor of the ship.
+// 22 Completed the Gugli quest.
+// 23 ChefGado Quest accepted.
+// 24 ChefGado Quest completed and "Introduction" chapter finalized.
+// 25 Reward taken from the box.
+
+000-2-0,27,24,0 script Julia NPC_JULIA,2,10,{
+
+ function ynMenu {
+ if (select(l("Yes, I do."), l("No, none.")) == 1) {
+ return;
+ }
+ closedialog;
+ }
+
+ function poisonJulia {
+ mes "";
+ mesn;
+ mesq l("Seems yummy! Let me taste it!");
+ next;
+ mesq l("Hmmm, hm... *cough*, *cough*, *burp*, *cough*. What... What is that?!... *cough*, *burp*... Damn Gado... *cough*");
+ if (countitem(PoisonedDish) > 0) delitem PoisonedDish, 1;
+ setq ShipQuests_ChefGado, 3;
+ close;
+ }
+
+ function gotoSleep {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You already did enough for us, follow Nard's advice and get some rest."),
+ l("We are at half a day from our final destination, by the time that you wake up I'm sure that we will be there!"),
+ l("Do you have any other questions for me?");
+ ynMenu;
+ return;
+ }
+
+ function heardRumors {
+ mes "";
+ mesn;
+ mesq l("You shouldn't believe every tale drunken sailors tell you.");
+ next;
+
+ select
+ l("Let's say the person who told me about that is well respected on this ship and never drunk.");
+
+ mes "";
+ mesn;
+ mesq l("Hahaha! All sailors aboard this ship are always drunk... Well... Except... Wait, what?! Nard told you?!");
+ next;
+ mesq l("Doesn't he like the way I'm taking care of his ship? Everything is clean and tidy with me, rightful lieutenant of La Johanne.");
+ next;
+ mesq l("I give tasks to every single sailor, all day long. That should make him happy!");
+ next;
+
+ select
+ l("Well... I don't think it is the best way to rule a ship. Think about it."),
+ l("In fact, everything seems to work perfectly under your guidance. Nard has made the right choice.");
+
+ if (@menu == 1)
+ {
+ closedialog;
+ end;
+ }
+
+ mes "";
+ mesn;
+ mesq l("I'm glad you're on my side.");
+ next;
+ mesq l("Take this money as a reward for your nice words.");
+
+ setq ShipQuests_ChefGado, 6;
+ Zeny += 100;
+ message strcharinfo(0), l("You receive @@ E!", 100);
+ getexp 8, 0;
+ close;
+ }
+
+ function gotRegrets {
+ mes "";
+ mesn;
+ mesq l("Why? And who should you bring it back to?");
+ next;
+
+ select
+ l("Ehm... He was really upset because of some past stories.");
+
+ mes "";
+ mesn;
+ mesq l("Gado! That coward lives in the past, I will ask Nard to punish him, again!");
+ next;
+ mesq l("Take this money for your wise choice. But do not try it again. The open sea has been merciful with you once... Do not further tempt the fates!");
+
+ setq ShipQuests_ChefGado, 5;
+ Zeny += 200;
+ message strcharinfo(0), l("You receive @@ E!", 200);
+ getexp 15, 0;
+ close;
+ }
+
+ function basicSkill {
+ mes "";
+ mesn;
+ mesq l("Let me check into it...");
+ next;
+ adddefaultskills;
+ mesq l("Here you go, everything is fixed.");
+ emotion E_HAPPY;
+ next;
+ mesq l("Do you have any other questions for me?");
+ next;
+ ynMenu;
+ return;
+ }
+
+ function chooseLang {
+ mes "";
+ mesn;
+ mesq l("Of course! Tell me which language you speak and I will change the note on the ship passenger list.");
+ next;
+
+ asklanguage(LANG_IN_SHIP);
+
+ mes "";
+ mesn;
+ mesq l("Ok, done.");
+
+ if (getq(ShipQuests_Julia) == 2)
+ {
+ next;
+ mesq l("Do you have any other questions for me?");
+ next;
+ ynMenu;
+ return;
+ }
+
+ next;
+ mesq l("I'm sure that you've got some questions for me, feel free to ask them, but first I need to tell you the rules of proper social conduct on board.");
+
+ mesq l("Here they are.");
+ next;
+
+ narrator S_LAST_NEXT,
+ l("There is a paper with some rules written on it.");
+
+ GameRules 8 | 4;
+
+ mesn;
+ mesq l("Oh, and I almost forgot! Do not give the password of your room to anybody! I am the only one who has the other key and I won't ask for yours so keep it secret and try not to use the same password for any other room in the future.");
+ next;
+ mesq l("If you want to read this page again, there is a copy up on the left wall.");
+ next;
+ mesq l("You can also read The Book of Laws at any time to see the rules.");
+ next;
+ mesq l("I think I'm done with that now. Do you have any questions?");
+ next;
+
+ setq ShipQuests_Julia, 2;
+ return;
+ }
+
+ function whereAmI {
+ mes "";
+ mesn;
+ mesq l("You're on a ship, we're on our way to the commercial capital of Artis.");
+ next;
+ mesq l("We should be there in a few days, once we arrive, I will warn the Legion of Aemil about what happened, I'm sure they can help.");
+ next;
+ mesq l("But for now, you can relax on the ship, or visit the island we're docked at! Its a small island, but a good place to get some exercise and stretch your legs.");
+ next;
+ mesq l("Do you have any other questions for me?");
+ next;
+ ynMenu;
+ return;
+ }
+
+ function whatHappened {
+ mes "";
+ mesn;
+ mesq l("We thought that you could help us understand this, all we know is that we found you cast in the sea, adrift on your raft.");
+ next;
+ mesq lg("You were in bad shape, you should be happy we found you before the sea killed you.");
+ next;
+ mesq l("Oh, and there was this inscription on your raft. It represents the Legion of Aemil, one of the four main guilds of Gasaron. Does that help you remember anything, anything at all?");
+ next;
+
+ select
+ l("Sorry, but I can't tell you anything about that."),
+ l("Nothing, sorry.");
+
+ mes "";
+ mesn;
+ mesq l("No problem, do you have any other questions for me?");
+ next;
+ ynMenu;
+ return;
+ }
+
+ function readRules {
+ mes "";
+ mesn;
+ mesq l("Of course, they are on the left wall, go have a look at them.");
+ next;
+ mesq l("Do you have any other questions for me?");
+ next;
+ ynMenu;
+ return;
+ }
+
+ function mainMenu {
+ do
+ {
+ .@q2 = getq(ShipQuests_ChefGado);
+ .@q3 = getq(ShipQuests_Nard);
+ .@q4 = getq(General_Narrator);
+
+ selectd
+ rif(.@q3 == 5 && .@q4 < 1, l("What can I do now?")),
+ rif(.@q3 == 3 && .@q2 == 0, l("I heard rumors about some old hostilities between you and Gado. Are they true?")),
+ rif(.@q2 == 2 && countitem(PoisonedDish), l("Well... No wait, I have something for you but you shouldn't eat it... I'm taking it back to the kitchen.")),
+ rif(.@q2 == 2 && countitem(PoisonedDish), l("I have brought you a tasty present for your delicate mouth.")),
+ rif(getskilllv(NV_BASIC) < 6, l("Something is wrong with me, I can't smile nor sit.")),
+ lg("I made a mistake, I would like to change my language."),
+ l("Could you explain to me where I am?"),
+ l("What happened to me?"),
+ l("Can I read these rules again?"),
+ l("Nothing, sorry.");
+
+ switch (@menu)
+ {
+ case 1: gotoSleep; break;
+ case 2: heardRumors; break;
+ case 3: gotRegrets; break;
+ case 4: poisonJulia; break;
+ case 5: basicSkill; break;
+ case 6: chooseLang .@s$; break;
+ case 7: whereAmI; break;
+ case 8: whatHappened; break;
+ case 9: readRules; break;
+ case 10: closedialog; end;
+ }
+ } while (1);
+ }
+
+ mesn;
+ mesq lg("Hello dear!");
+ next;
+ mesq l("What do you want today?");
+ next;
+
+ mainMenu;
+
+OnTouch:
+ .@q = getq(ShipQuests_Julia);
+ if (.@q > 1) end;
+
+ checkclientversion;
+
+ mesn;
+ mesq l("Hi, nice to see you!");
+ next;
+ mesq l("My name is Julia, it is me who took care of you after we found you in the sea.");
+ next;
+ mesq lg("I'm glad to see you're okay.");
+ next;
+ mesq lg("Could I ask you what your native language is? A sailor told me you're Russian, but another one told me you're French... I'm a bit lost. I will register you on the ship passenger list just after that.");
+ next;
+ chooseLang;
+ mainMenu;
+ end;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 10;
+ .quest_debug = ShipQuests_Julia;
+}
diff --git a/npc/000-2-0/mapflags.txt b/npc/000-2-0/mapflags.txt
new file mode 100644
index 000000000..d3a4bd222
--- /dev/null
+++ b/npc/000-2-0/mapflags.txt
@@ -0,0 +1 @@
+000-2-0 mapflag town
diff --git a/npc/000-2-0/note.txt b/npc/000-2-0/note.txt
new file mode 100644
index 000000000..fcb28f717
--- /dev/null
+++ b/npc/000-2-0/note.txt
@@ -0,0 +1,27 @@
+// Evol scripts.
+// Authors:
+// gumi
+// Qwerty Dragon
+// Reid
+// WildX
+// Description:
+// A small note presenting the 6 main rules of Evol Online.
+
+000-2-0,29,25,0 script Note NPC_PAPER_NOTE,{
+ narrator S_LAST_NEXT,
+ l("There is a paper with some rules written on it.");
+
+ GameRules 8 | 4;
+
+ narrator S_NO_NPC_NAME,
+ l("Following these lines are some other writings on this paper."),
+ l("Do not give the password of your room to anybody! Keep it secret and try not to use the same one in any other room in the future. - Julia"),
+ l("Does anyone know a good place to hang out in Esperia? - M. Arpan"),
+ l("Other things are written but are not legible anymore.");
+
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-1/_import.txt b/npc/000-2-1/_import.txt
new file mode 100644
index 000000000..ba87b23ef
--- /dev/null
+++ b/npc/000-2-1/_import.txt
@@ -0,0 +1,17 @@
+// Map 000-2-1: Second Deck
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/000-2-1/_mobs.txt",
+"npc/000-2-1/_savepoints.txt",
+"npc/000-2-1/_warps.txt",
+"npc/000-2-1/alige.txt",
+"npc/000-2-1/arpan.txt",
+"npc/000-2-1/chefgado.txt",
+"npc/000-2-1/chest.txt",
+"npc/000-2-1/dan.txt",
+"npc/000-2-1/devis.txt",
+"npc/000-2-1/hammock.txt",
+"npc/000-2-1/knife.txt",
+"npc/000-2-1/mapflags.txt",
+"npc/000-2-1/peter.txt",
+"npc/000-2-1/q'onan.txt",
+"npc/000-2-1/story_save.txt",
diff --git a/npc/000-2-1/_mobs.txt b/npc/000-2-1/_mobs.txt
new file mode 100644
index 000000000..b02288acf
--- /dev/null
+++ b/npc/000-2-1/_mobs.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-2-1: Second Deck mobs
+000-2-1,52,32,21,9 monster Piou 1002,3,30000,20000
+000-2-1,52,32,21,9 monster Maggot 1030,2,30000,20000 \ No newline at end of file
diff --git a/npc/000-2-1/_savepoints.txt b/npc/000-2-1/_savepoints.txt
new file mode 100644
index 000000000..14b79c7e4
--- /dev/null
+++ b/npc/000-2-1/_savepoints.txt
@@ -0,0 +1,38 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-2-1: Second Deck saves
+000-2-1,40,37,0 script #save_000-2-1_40_37 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, NO_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+000-2-1,46,37,0 script #save_000-2-1_46_37 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, NO_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+000-2-1,50,38,0 script #save_000-2-1_50_38 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, NO_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+000-2-1,55,40,0 script #save_000-2-1_55_40 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, NO_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/000-2-1/_warps.txt b/npc/000-2-1/_warps.txt
new file mode 100644
index 000000000..db3a1c8e8
--- /dev/null
+++ b/npc/000-2-1/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-2-1: Second Deck warps
+000-2-1,72,30,0 warp #000-2-1_72_30 0,0,000-2-0,31,26
diff --git a/npc/000-2-1/alige.txt b/npc/000-2-1/alige.txt
new file mode 100644
index 000000000..cc57c0d7a
--- /dev/null
+++ b/npc/000-2-1/alige.txt
@@ -0,0 +1,320 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Alige
+// Qwerty Dragon
+// Reid
+// Vasily_Makarov
+// Description:
+// Hidden in a ship's hole.
+// 2 bits array:
+// ShipQuests
+// Variable:
+// ShipQuests_Alige
+// Values:
+// 0 Never talk.
+// 1 First talk.
+// 2 Accept the task.
+// 3 Bring first food.
+
+000-2-1,43,32,0 script AligeTrigger NPC_HIDDEN,1,1,{
+
+OnTouch:
+ if (getareausers() <= 1)
+ {
+ setnpcdir "Alige", 2;
+ stopnpctimer;
+ initnpctimer;
+ }
+
+ if (getq(ShipQuests_Alige) > 0) close;
+ doevent "Alige::OnFirstEncounter";
+
+ close;
+
+OnUnTouch:
+ if (getareausers() == 0)
+ {
+ setnpcdir "Alige", 4;
+ stopnpctimer;
+ initnpctimer;
+ }
+ close;
+
+OnTimer190:
+ stopnpctimer;
+
+ if (getnpcdir("Alige") == 2) setnpcdir "Alige", 6;
+ if (getnpcdir("Alige") == 4) setnpcdir "Alige", 8;
+
+ end;
+}
+
+000-2-1,43,31,0 script Alige NPC_ALIGE,{
+ .@q = getq(ShipQuests_Alige);
+ if (.@q > 1) goto L_AskForFood;
+
+ goto OnFirstEncounter;
+
+OnFirstEncounter:
+ setq ShipQuests_Alige, 1;
+
+ setcamnpc;
+ mesn "Hidden Person";
+ mesq l("Hey, psst! You're not a sailor, right?");
+ next;
+ restorecam;
+
+ menu
+ lg("I am, who are you?"), -,
+ lg("Indeed, I am not."), L_NeedHelp;
+
+ mes "";
+ mesn "Narrator";
+ mes col(l("The stowaway doesn't answer."), 9);
+
+ close;
+
+L_NeedHelp:
+ setcamnpc;
+ mes "";
+ mesn "Hidden Person";
+ mesq l("Good, good... Hey, could you help me please? I beg you, please, pleeeease...");
+ next;
+ restorecam;
+
+ menu
+ l("Why not, but who are you, and what kind of help do you need?"), L_CanHelp;
+ l("Sorry but I have no time for this."), -;
+
+ closedialog;
+ close;
+
+L_CanHelp:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("My name is Alige, I've been hiding here for weeks. All I have to eat are these berries... berries... berries...");
+ next;
+ mesq l("I'm losing my mind here, I need something else to eat!");
+ next;
+ mesq l("Could you please bring me something which isn't a berry, and I'm not big on vegetables either. I need proteins!");
+ next;
+ restorecam;
+
+ menu
+ l("Sure, but what will you give me in exchange?"), L_AboutReward,
+ l("Why don't you come out?"), -;
+
+L_ExplainHiding:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("No, I can't. I won't! All I wanted was to travel across the seas for fun, growl... sniff. And in this hole in the floor, as you can see, I have lots of fun.");
+ next;
+ mesq l("Oh... um... actually... all I wanted was to get to Artis. Err... but I didn't, uhm... have enough money to pay for the ferry!");
+ next;
+ mesq l("Please don't tell people you saw me. I don't want to be decapitated or get thrown into the sea as food for sharks, or get my hair mussed!");
+ next;
+ restorecam;
+
+ if (getq(ShipQuests_Alige) == 2) goto L_SoAskForFood;
+ goto L_Accept;
+
+L_AboutReward:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("I'll share my berries with you if you help me.");
+ next;
+ restorecam;
+
+L_Accept:
+ menu
+ l("Understood, I will help you."), L_FirstAccepted,
+ l("What is Artis?"), L_Artis,
+ l("I think I should report you to the crew members."), -;
+
+ setcamnpc;
+ mesq lg("Growl, sniff, grr! You'd better not tell anyone you saw me!");
+
+ close;
+
+L_Artis:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("It's a commercial port of Andorra, it's weird that you don't know about it since it is one of the most famous cities throughout the whole world. But hey, back to me. Remember me telling you that I'm hun...grrr...eee!");
+ next;
+ restorecam;
+
+ if (.@q == 2) goto L_SoAskForFood;
+ goto L_Accept;
+
+L_FirstAccepted:
+ if (getq(ShipQuests_Alige) >= 2) goto L_Accepted;
+ setq ShipQuests_Alige, 2;
+
+ goto L_Accepted;
+
+L_Accepted:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq lg("Great, what food do you have for me today?");
+ next;
+ restorecam;
+
+L_GiveFood:
+ mes "";
+ menuint
+ rif(countitem(Acorn), l(getitemname(Acorn))), 0,
+ rif(countitem(Bread), l(getitemname(Bread))), 502,
+ rif(countitem(Fungus), l(getitemname(Fungus))), 503,
+ rif(countitem(Cheese), l(getitemname(Cheese))), 504,
+ rif(countitem(PiouLegs), l(getitemname(PiouLegs))), 505,
+ rif(countitem(LettuceLeaf), l(getitemname(LettuceLeaf))), 0,
+ rif(countitem(Piberries), l(getitemname(Piberries))), 2,
+ rif(countitem(SeaDrops), l(getitemname(SeaDrops))), 1,
+ rif(countitem(Aquada), l(getitemname(Aquada))), 509,
+ rif(countitem(PinkBlobime), l(getitemname(PinkBlobime))), 1,
+ rif(countitem(HalfCroconut), l(getitemname(HalfCroconut))), 512,
+ rif(countitem(Croconut), l(getitemname(Croconut))), 0,
+ rif(countitem(Plushroom), l(getitemname(Plushroom))), 515,
+ rif(countitem(PumpkinSeeds), l(getitemname(PumpkinSeeds))), 1,
+ rif(countitem(UrchinMeat), l(getitemname(UrchinMeat))), 1,
+ rif(countitem(EasterEgg), l(getitemname(EasterEgg))), 1,
+ rif(countitem(PumpkishJuice), l(getitemname(PumpkishJuice))), 527,
+ rif(countitem(Manana), l(getitemname(Manana))), 528,
+ rif(countitem(Curshroom), l(getitemname(Curshroom))), 529,
+ rif(countitem(Carrot), l(getitemname(Carrot))), 530,
+ rif(countitem(RedPlushWine), l(getitemname(RedPlushWine))), 3,
+ l("I don't have anything good for you today."), -1;
+
+ .@id = @menuret;
+ if (.@id == -1) goto L_Quit; // Quit message.
+ if (.@id == 0) goto L_NoReward; // In case of wrong food.
+ if (.@id == 1) goto L_Poison; // In case of poisoned food.
+ if (.@id == 2) goto L_NoMore; // In case of Piberries.
+ if (.@id == 3) goto L_Drunk; // In case of Alcohol.
+ if (countitem(.@id) == 0) goto L_Quit;
+// if (.@id == item's ID) then food is correct.
+// Do not put any other number than -1, 0, 1, 2 or the item's ID, that'll avoid confusion.
+
+ inventoryplace Piberries, 3;
+ delitem .@id, 1;
+
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("Thank you so much! Here, have some of my berries.");
+
+ setq ShipQuests_Alige, 3;
+ getitem Piberries, rand(1, 3);
+ next;
+
+ goto L_ReturnMenu;
+
+L_NoReward:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("You don't expect me to eat that, do you? Give me something else!");
+ next;
+ restorecam;
+
+ goto L_GiveFood;
+
+L_Drunk:
+ setcamnpc;
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I asked for food but... *hips* Ah, that'll do!");
+ restorecam;
+
+ goto L_GiveFood;
+
+L_ReturnMenu:
+ setcamnpc;
+ mesq l("Do you have anything else for me?");
+ next;
+ restorecam;
+
+ goto L_GiveFood;
+
+L_NoMore:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("Grr, don't give me more berries! I don't want them, stupid berries, stupid... Stupid... Stupid!");
+ next;
+
+ goto L_ReturnMenu;
+
+L_Poison:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("Don't try to poison me! I know what that does!");
+ next;
+ restorecam;
+ goto L_ReturnMenu;
+
+L_SoAskForFood:
+ setcamnpc;
+ mesn;
+ mesq l("So, do you have anything for me today?");
+ next;
+ restorecam;
+ goto L_IntroMenu;
+
+L_AskForFood:
+ setcamnpc;
+ mesn;
+ mesq l("Do you have anything for me today?");
+ next;
+ restorecam;
+
+L_IntroMenu:
+ menu
+ l("Yes."), L_GiveFood,
+ l("Where can I find some food?"), L_FindFood,
+ l("Why are you hiding?") + " " + l("Why don't you come out?"), L_ExplainHiding,
+ l("What is Artis?"), L_Artis,
+ l("I think I should report you to the crew members."), -;
+
+ setcamnpc;
+ mesq lg("Growl, sniff, grr! You'd better not tell anyone you saw me!");
+
+ close;
+
+L_FindFood:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("There are some flying yellow plushes around you. They're called pious. Getting a roasted leg of one of them would be perfect.");
+ next;
+ mesq l("I'd like to catch one of them, but they fly away when I try.");
+ next;
+ mesq l("Walking around a bit, it'll be easy for you to catch one, I bet. Impale one of them for me please.");
+ next;
+ restorecam;
+ mesn "Narrator";
+ mes col(l("You can attack a monster by clicking on it, or from your keyboard you can press the 'A' key to select the monster followed by 'Ctrl' to attack it."), 9);
+ next;
+ mes col(l("Once the monster is dead, click on the dropped items to add them to your inventory. You can also use the 'Z' key to claim the drops."), 9);
+
+ close;
+
+L_Quit:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("Too bad... Come back when you'll have some nice food for me. Growl... grumble... grumble.");
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-1/arpan.txt b/npc/000-2-1/arpan.txt
new file mode 100644
index 000000000..9207e03df
--- /dev/null
+++ b/npc/000-2-1/arpan.txt
@@ -0,0 +1,272 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Qwerty Dragon
+// Description:
+// Explains to the player how he got here.
+// Variable:
+// 0 ShipQuests_Arpan
+// 1 ShipQuests_Julia
+// Values:
+// 00 Has not talked to Arpan yet.
+// 01 Talked to Arpan and needs to get the clothes.
+// 02 Has the clothes.
+// 03 Has and equipped the clothes.
+// 10 Has not talked to Julia
+// 11 Need to see Julia
+// 12 Has been registered by Julia
+
+000-2-1,49,36,0 script LeftDoorCheck NPC_HIDDEN,0,0,{
+ .@q = getq(ShipQuests_Arpan);
+ if (.@q == 0) doevent "Magic Arpan::OnTalk";
+
+ close;
+}
+
+000-2-1,54,36,0 script RightDoorCheck NPC_HIDDEN,0,0,{
+ .@q = getq(ShipQuests_Arpan);
+ if (.@q == 0) doevent "Magic Arpan::OnTalk";
+
+ close;
+}
+
+000-2-1,47,32,0 script LeftBarrierCheck NPC_HIDDEN,0,2,{
+ .@q = getq(ShipQuests_Arpan);
+ if (.@q > 2) close;
+ if (.@q == 2 && getequipid(equip_torso) == 1300 && getequipid(equip_legs) == 2200) goto L_EquipDone;
+ if (.@q == 2) goto L_Equip;
+ if (.@q == 1) goto L_GetCloth;
+
+ doevent "Magic Arpan::OnClothNotTaken";
+
+L_Equip:
+ warp "000-2-1", 49, 32;
+ doevent "Magic Arpan::OnEquip";
+
+ close;
+
+L_GetCloth:
+ warp "000-2-1", 49, 32;
+ doevent "Magic Arpan::OnClothNotTaken";
+
+ close;
+
+L_EquipDone:
+ setq ShipQuests_Arpan, 3;
+
+ close;
+}
+
+000-2-1,56,32,0 script RightBarrierCheck NPC_HIDDEN,0,2,{
+ .@q = getq(ShipQuests_Arpan);
+ if (.@q > 2) close;
+ if (.@q == 2 && getequipid(equip_torso) == 1300 && getequipid(equip_legs) == 2200) goto L_EquipDone;
+ if (.@q == 2) goto L_Equip;
+ if (.@q == 1) goto L_GetCloth;
+
+ doevent "Magic Arpan::OnClothNotTaken";
+
+L_Equip:
+ warp "000-2-1", 55, 32;
+ doevent "Magic Arpan::OnEquip";
+
+ close;
+
+L_GetCloth:
+ warp "000-2-1", 55, 32;
+ doevent "Magic Arpan::OnClothNotTaken";
+
+ close;
+
+L_EquipDone:
+ setq ShipQuests_Arpan, 3;
+
+ close;
+}
+
+000-2-1,49,33,0 script Magic Arpan NPC_MAGIC_ARPAN,{
+ .@q = getq(ShipQuests_Arpan);
+ .@q_nard = getq(ShipQuests_Nard);
+ .@q_julia = getq(ShipQuests_Julia);
+ if (.@q == 2 && getequipid(equip_torso) == 1300 && getequipid(equip_legs) == 2200) goto L_EquipDone;
+
+OnTalk:
+ mesn;
+
+ if (.@q > 0) goto L_Menu;
+
+ mesq lg("Yeye, you are really lucky to be alive. You are in good enough shape for walking, do you remember what happened?");
+ next;
+ setq ShipQuests_Arpan, 1;
+
+ menu
+ lg("I only remember I was rescued by you."), L_Story,
+ lg("I can't remember anything."), L_OhWell;
+
+OnClothNotTaken:
+ mesn;
+ mesq lg("Yeye, you still did not get your new clothes from the chest next to your bed!");
+
+ close;
+
+OnEquip:
+ mesn "Narrator";
+ mes col(l("To open your inventory, use the F3 key or use your mouse to select it in the above menu in your client."), 9);
+ next;
+ mes col(l("When your inventory is open, you can equip an item by selecting it and clicking 'Equip'. You can do the same to remove an item by clicking on 'Unequip'."), 9);
+ next;
+ mes col(l("Items have different effects. Some will heal you, some can be used as weapons or armor, and some can be sold for gold."), 9);
+
+ close;
+
+L_OhWell:
+ mes "";
+ mesq lg("Oh well, we rescued you when you were yaying adrift in the sea.");
+ next;
+
+ select
+ l("And then what happened?");
+
+L_Story:
+ mes "";
+ mesq lg("You were yaying sleeping for quite some time there. Our shipkeeper, Julia, was here with you, and she did her best to heal your injuries.");
+ next;
+ if (.@q_julia == 0) setq ShipQuests_Julia, 1;
+ mesq lg("Yaya, you should go see her! She'll be happy to see you.");
+ next;
+ mesq lg("Also, we took your yayed clothes, as they were... Yeyeye... In a bad shape. Go check the chest near your bed, there are some other ones inside.");
+ setcamnpc "Chest";
+
+ close;
+
+L_Menu:
+ mesq l("What yeye could I do for you today?");
+ next;
+ .@equipped = getequipid(equip_torso) == 1300 && getequipid(equip_legs) == 2200;
+
+ menu
+ rif(.@q_nard == 5 && getq(General_Narrator) < 1, l("What can I do now?")), L_GotoSleep,
+ lg("Could you tell me where I am?"), L_Where,
+ lg("Where can I find Julia?"), L_Julia,
+ l("Who are you?"), L_Who,
+ rif(getq(ShipQuests_ArpanMoney) == 1, lg("Do you know what happened to the gold I had when you guys saved me?")), L_WhereMoney,
+ rif(getq(ShipQuests_ArpanMoney) < 2, l("Where are my old clothes?")), L_WhereOldClothes,
+ rif(!.@equipped, lg("What should I do after taking these clothes?")), L_WhatCloth,
+ rif(!.@equipped, l("Thank you, I'll take them and put them on.")), -,
+ l("Nothing, sorry."), -;
+
+ closedialog;
+ close;
+
+L_Where:
+ mes "";
+ mesn;
+ mesq lg("You're on our ship, we made port to a little island and we're actually yeyending our long merchant traveling adventure at the city of Artis.");
+ next;
+ mesq l("We will be yaying there in a few days, so we will drop you off there.");
+ next;
+ mesq l("You will see, citizens are polite and you can still ask for help in the Legion of Aemil. They can help find a job for you or maybe help you find out what happened to you out at sea!");
+ next;
+
+ goto L_Menu;
+
+L_Julia:
+ mes "";
+ mesn;
+ mesq lg("She's on the upper level, yeye can't miss her. She's the only girl in this crew, oh well, except for you now yeyeye!", "She's on the upper level, yeye can't miss her. She's the only girl in this crew.");
+ next;
+
+ mesn "Narrator";
+ mes col(l("Julia is on the upper level of the ship, use the arrow keys to walk to the stairs or click on the stairs at the top right of your screen."), 9);
+ next;
+
+ goto L_Menu;
+
+L_Who:
+ mes "";
+ mesn;
+ mesq l("Sorry! I forgot to introduce myself. My name is Arpan, but other sailors call me Magic Arpan because I know one or two yaing magic spells.");
+ next;
+
+ goto L_Menu;
+
+L_WhereOldClothes:
+ mes "";
+ mesn;
+ mesq lg("We tried to clean them but the sea water mostly destroyed them. It's why we gave you these clothes. They're not very nice, but that's all that we have for you.");
+ next;
+ mes lg("Oh, now that I remember, we also found some money in your pockets, here it is!");
+ next;
+
+ setq ShipQuests_ArpanMoney, 2;
+ .@q = getq(ShipQuests_Arpan);
+ Zeny = Zeny + 10;
+ message strcharinfo(0), l("You receive @@ E!", 10);
+
+ goto L_BeforeMenu;
+
+L_WhereMoney:
+ mes "";
+ mesn;
+ mesq l("Oh right, I totally forgot about that, here you go.");
+ next;
+
+ setq ShipQuests_ArpanMoney, 2;
+ .@q = getq(ShipQuests_Arpan);
+ Zeny = Zeny + 10;
+ message strcharinfo(0), l("You receive @@ E!", 10);
+
+ goto L_BeforeMenu;
+
+L_WhatCloth:
+ mes "";
+ mesn;
+ mesq lg("Oh yeyeye... As they are not edible, you can maybe try to equip them?");
+ next;
+
+ mesn "Narrator";
+ mes col(l("To open your inventory, use the F3 key or use your mouse to select it in the above menu in your client."), 9);
+ next;
+ mes col(l("When your inventory is open, you can equip an item by selecting it and clicking 'Equip'. You can do the same to unequip an item by clicking on 'Unequip'."), 9);
+ next;
+ mes col(l("Items have different effects. Some will heal you, some can be used as weapons or armor, and some can be sold for gold."), 9);
+ next;
+
+L_BeforeMenu:
+ mesn;
+ goto L_Menu;
+
+L_EquipDone:
+ setq ShipQuests_Arpan, 3;
+ goto L_Menu;
+
+L_GotoSleep:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You already did enough for us, do you want to follow Nard's advice and get some rest?");
+
+ switch (select(l("Yes."), l("No.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Fine."),
+ l("We are at half a day from our final destination, by the time that you wake up I'm sure that we will be there!");
+
+ closedialog;
+ doevent "#name3::OnClick";
+ close;
+
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Alright, take your time we are not in a hurry.");
+
+ break;
+ }
+
+ goto L_Menu;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 5;
+ end;
+}
diff --git a/npc/000-2-1/chefgado.txt b/npc/000-2-1/chefgado.txt
new file mode 100644
index 000000000..ca069d8e0
--- /dev/null
+++ b/npc/000-2-1/chefgado.txt
@@ -0,0 +1,213 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Description:
+// La Johanne Chef.
+// Variable:
+// ShipQuests_ChefGado
+// ShipQuests_Nard
+// Values:
+// 0 Default, no quest given.
+// 1 Quest accepted.
+// 2 Ingredients collected, ready to poison Julia.
+// 3 Julia poisoned.
+// 4 Quest complete. Chef Gago wins.
+// 5 Quest complete. Julia wins (poison dish returned).
+// 6 Quest complete. Julia wins.
+
+000-2-1,27,28,0 script Chef Gado NPC_CHEF_GADO,{
+ .@q = getq(ShipQuests_ChefGado);
+ .@n = getq(ShipQuests_Nard);
+ if (.@q == 1) goto L_QuestAccepted;
+ if (.@q == 2) goto L_PoisonAccepted;
+ if (.@q == 3) goto L_PoisonJulia;
+ if (.@q == 4) goto L_QuestComplete;
+ if (.@q == 5 && countitem(PoisonedDish) > 0) goto L_Aborting;
+ if (.@q > 4) goto L_QuestAborted;
+ if (.@n == 3) goto L_QuestStart;
+
+ mesn;
+ .@r = rand(3);
+ if (.@r == 0) mesq l("What are you doing in my kitchen?! Get out, it's not a place for kids!");
+ if (.@r == 1) mesq l("Where is the damn salt?! Give me the salt, I know you have it!");
+ if (.@r == 2) mesq l("Are you going to stand here all day long? Do the dishes or go away.");
+
+ close;
+
+L_QuestStart:
+ mesn;
+ mesq l("So it seems I have another stomach to fill. Those bastards have no respect for who feeds them every damn day!");
+ next;
+
+ menu
+ l("How rude! What is the reason behind your malice?"), L_Rude,
+ l("I swear, I do not eat so much."), -;
+
+ mes "";
+ mesn;
+ mesq l("Yeah, yeah, of course you don't...");
+
+ close;
+
+L_Rude:
+ mes "";
+ mesn;
+ mesq l("UAHAHAHAAH! I am the cook of that bunch of donkeys, and I can be rude with everyone from this bossy captain to that harpy-lady!");
+ next;
+
+ select
+ l("Harpy-lady?");
+
+ mes "";
+ mesn;
+ mesq l("I am sure you know her. Nice dress, large smile and a constant flux of orders and rules. Julia they call her!");
+ next;
+ mesq l("You have to know that there was a time during which I was the unopposed lieutenant of this crew. Then one day one of those damn sailors brought that 'nice' lady here.");
+ next;
+ mesq l("I will not tell you all the details, but after a month, she was ruling the ship and I was sent down here, cooking for those traitors!");
+ next;
+ mesq l("But I swear that one day... Oh... My tasty revenge! Hhm, actually I wonder if... Maybe...");
+ next;
+
+ select
+ l("M... Maybe?");
+
+ mes "";
+ mesn;
+ mesq lg("Well, eh-heh... Welcome aboard, cutie!", "Well, eh-heh... Welcome aboard, son!");
+ next;
+ mesq l("I just realized I am lacking some common things, and one key ingredient, to prepare a... A special recipe.");
+ next;
+ mesq l("I only need 2 @@, 2 @@s, 1 @@...", getitemlink(PiouLegs), getitemlink(HalfCroconut), getitemlink(Aquada));
+ next;
+ mesq l("... and 1 @@.", getitemlink(SeaDrops));
+ next;
+
+ menu
+ l("Sea water?! I will not help you with your evil plan!"), L_Quit,
+ l("Sure, why not?"), -;
+
+ setq ShipQuests_ChefGado, 1;
+ mes "";
+ mesn;
+ mesq lg("Well done! Collect all the ingredients and then come back here. You will be rewarded once I am satisfied that they understand who rules this ship!");
+ next;
+ mesq l("Before you go, let me tell you how to get @@s, because you don't look very smart.", getitemlink(HalfCroconut));
+
+ goto L_OpenCroconut;
+
+L_QuestAccepted:
+ mesn;
+ mesq l("Have you collected all the ingredients for my recipe? The special one too?");
+ next;
+
+ menu
+ rif(countitem(PiouLegs) > 1 && countitem(HalfCroconut) > 1 && countitem(Aquada) > 0 && countitem(SeaDrops) > 0, l("All your... Fresh ingredients are ready to be cooked.")), L_GotAll,
+ l("What are your needs?"), L_Need,
+ l("Where can I find a half croconut?"), L_OpenCroconut,
+ l("Not yet. I will be back soon."), L_Quit;
+
+L_OpenCroconut:
+ mes "";
+ mesn;
+ mesq lg("Take a @@ and try opening it using something like a sharp knife. I doubt you'll succeed, you're being so weak in everything.",
+ "Take a @@ and try opening it using something like a sharp knife. I doubt you'll succeed, you're being so weak in everything.", getitemlink(Croconut));
+ next;
+ mesq l("Now move!");
+
+ close;
+
+L_GotAll:
+ mes "";
+
+ inventoryplace PoisonedDish, 1;
+
+ delitem PiouLegs, 2;
+ delitem HalfCroconut, 1;
+ delitem Aquada, 1;
+ delitem SeaDrops, 1;
+
+ mesn;
+ mesq l("Let me see... Crispy legs, disgusting liquids... Let's start!");
+ next;
+ mesq l("Water, salt, spicy herbs and meat stuffed with my special surprise!");
+ next;
+ mesq l("Done. Here, take it! Now, here is the plan. Go talk to her and offer our beautiful lady a bite of her arrogance!");
+
+ setq ShipQuests_ChefGado, 2;
+ getitem PoisonedDish, 1;
+ close;
+
+L_Need:
+ mes "";
+ mesn;
+ mesq l("Shhht, don't say it that loud...");
+ next;
+ mesq l("I only need 2 @@, 2 @@s, 1 @@...", getitemlink(PiouLegs), getitemlink(HalfCroconut), getitemlink(Aquada));
+ next;
+ mesq l("... and 1 @@.", getitemlink(SeaDrops));
+
+ close;
+
+L_PoisonAccepted:
+ mesn;
+ mesq l("Fool! Just come back here when you'll be done with our little... 'Secret mission'.");
+
+ close;
+
+L_PoisonJulia:
+ mesn;
+ mesq l("The usurper has been punished! This is a great day! Take this reward as a prize for your loyalty to the old commander!");
+
+ setq ShipQuests_ChefGado, 4;
+ Zeny = Zeny + 200;
+ message strcharinfo(0), l("You receive @@ E!", 200);
+ inventoryplace Bread, 1;
+ getitem Bread, 1;
+ getexp 15, 0;
+
+ close;
+
+L_QuestComplete:
+ mesn;
+ mesq l("Oh, it's you. I think it's better we do not talk for a while. They suspect something.");
+
+ close;
+
+L_Aborting:
+ mesn;
+ mesq l("Wait, why do you still have the dish with you?!");
+ next;
+
+ select
+ l("I informed Julia about your monstrous plan.");
+
+ mes "";
+ mesn;
+ mesq l("Are you mad?!");
+ next;
+ mesq lg("Give me back this dish, you dirty liar!");
+
+ if (countitem(PoisonedDish) > 0) delitem PoisonedDish, 1;
+
+ next;
+ mesq l("You're like the rest of this filthy crew, I can't trust you!");
+
+ close;
+
+L_QuestAborted:
+ mesn;
+ mesq lg("You're like the rest of this filthy crew. Your name is now on the traitors list!");
+
+ close;
+
+L_Quit:
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-1/chest.txt b/npc/000-2-1/chest.txt
new file mode 100644
index 000000000..3f5655218
--- /dev/null
+++ b/npc/000-2-1/chest.txt
@@ -0,0 +1,72 @@
+// Evol scripts.
+// Authors:
+// 4144
+// gumi
+// omatt
+// Reid
+// Description:
+// A box with clothes for new players.
+// Variable:
+// ShipQuests_Arpan
+// Values:
+// 1 Talked to Arpan and needs to get clothes.
+// 2 Has the clothes.
+
+000-2-1,51,37,0 script Chest#000-2-1 NPC_CHEST_BIG,2,4,{
+
+ .@questState = getq(ShipQuests_Arpan);
+
+ if (.@questState == 0)
+ {
+ npctalk3 l("You should talk to Magic Arpan first.");
+ end;
+ }
+
+ if (.busy == false)
+ {
+ if (.@questState <= 1)
+ {
+ inventoryplace CreasedShirt, 2;
+ setq ShipQuests_Arpan, 2;
+ getitem CreasedShirt, 1;
+ getitem CreasedShorts, 1;
+ npctalk3 l("You take the clothes from the chest.");
+ }
+
+ specialeffect(.dir == 0 ? 24 : 25, AREA, getnpcid(0)); // closed ? opening : closing
+ .dir = .dir == 0 ? 2 : 6; // closed ? opening : closing
+ .busy = true; // lock the animation
+ initnpctimer;
+ }
+ end;
+
+OnTimer220:
+ .dir = .dir == 6 ? 0 : 4; // closing ? closed : open
+ end;
+
+OnTimer500:
+ .busy = false; // unlock
+
+ if (.dir == 0)
+ {
+ stopnpctimer; // stop here if the chest is closed
+ }
+ end;
+
+OnUnTouch:
+ if (getareausers(.x - 2, .y - 4, .x + 2, .y + 6) > 0 || .dir == 0)
+ {
+ end;
+ }
+OnTimer30000:
+ .busy = true;
+ .dir = 6; // closing
+ specialeffect(25, AREA, getnpcid(0)); // closing
+ setnpctimer 0;
+OnTouch:
+ end;
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-1/dan.txt b/npc/000-2-1/dan.txt
new file mode 100644
index 000000000..8c6cc4797
--- /dev/null
+++ b/npc/000-2-1/dan.txt
@@ -0,0 +1,94 @@
+// Evol scripts.
+// Authors:
+// Qwerty Dragon
+// Reid
+// Description:
+// There are two kinds of dialogues in this script.
+// Dan will randomly choose between a useless sentence, and a quest in Artis.
+
+000-2-1,32,31,0 script Dan#000-2-1 NPC_DEMON_MAN,{
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ close;
+ }
+
+ mesn;
+ .@q = rand(3);
+ if (.@q == 0) goto L_QuestStory;
+
+ mesq l("You see these pious around us?");
+ next;
+ mesq l("It seems that we are close to an island, we should take a look at the upper level.");
+
+ close;
+
+L_QuestStory:
+ mesq l("It's so hard to find the motivation...");
+ next;
+
+ menu
+ l("Why?"), -,
+ l("I guess so... I will leave you alone."), L_Quit;
+
+ mes "";
+ mesn;
+ mesq l("Oh, it's you.");
+ next;
+ mesq lg("So, you finally woke up? We all thought you were in something like... You know, one of these long comas.");
+ next;
+
+ menu
+ l("I'm still in a coma, but my ghost is haunting you!"), L_Quit,
+ l("It was something like a long nap."), -;
+
+ mes "";
+ mesn;
+ mesq l("It's good, good... I have a friend who is still in a coma, but I can't be with her without working...");
+ next;
+ mesq l("The fear to see her sleeping on this quiet and lonely bed is becoming more and more unbearable, I think that I won't get the bravery to see her this time...");
+ next;
+
+ menu
+ l("Who is she?"), L_She,
+ l("Do you want me to go see her instead of you?"), L_Quest;
+ l("I don't know what to say..."), -;
+
+ mes "";
+ mesn;
+ mesq lg("There's nothing to say, don't worry miss.", "There's nothing to say, don't worry sir.");
+
+ close;
+
+L_She:
+ mes "";
+ mesn;
+ mesq l("She is a good friend of mine... We wanted to marry a few weeks before her accident but...");
+ next;
+
+ goto L_Quit2;
+
+L_Quest:
+ mes "";
+ mesn;
+ mesq l("I don't think that we are in a good place to talk about this...");
+ next;
+
+L_Quit:
+ mes "";
+ mesn "Narrator";
+ mes col(l("Dan keeps silent since your last question."), 9);
+
+ close;
+
+L_Quit2:
+ mesn "Narrator";
+ mes col(l("Dan ends the conversation and resumes to write his letter."), 9);
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-1/devis.txt b/npc/000-2-1/devis.txt
new file mode 100644
index 000000000..caf421bfb
--- /dev/null
+++ b/npc/000-2-1/devis.txt
@@ -0,0 +1,17 @@
+// Evol scripts.
+// Authors:
+// Alige
+// Reid
+// Vasily_Makarov
+// Description:
+// Sleeping and grumbling NPC.
+
+000-2-1,32,38,0 script Devis NPC_HAMMOC,{
+ asleep;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-1/hammock.txt b/npc/000-2-1/hammock.txt
new file mode 100644
index 000000000..3e188eedf
--- /dev/null
+++ b/npc/000-2-1/hammock.txt
@@ -0,0 +1,125 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Animated hammock at the mid level of the ship.
+
+000-2-1,32,27,0 script #hammock1 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+000-2-1,32,25,0 script #hammock2 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+000-2-1,37,25,0 script #hammock3 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+000-2-1,37,27,0 script #hammock4 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+000-2-1,37,29,0 script #hammock5 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+000-2-1,37,34,0 script #hammock6 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+000-2-1,37,36,0 script #hammock7 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+000-2-1,37,38,0 script #hammock8 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+000-2-1,32,40,0 script #hammock9 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+000-2-1,37,40,0 script #hammock10 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
diff --git a/npc/000-2-1/knife.txt b/npc/000-2-1/knife.txt
new file mode 100644
index 000000000..d8d1d54ad
--- /dev/null
+++ b/npc/000-2-1/knife.txt
@@ -0,0 +1,47 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Qwerty Dragon
+// Description:
+// Knife on the table.
+// Variable:
+// ShipQuests_Knife
+// Values:
+// 0 Default, not taken.
+// 1 Knife taken.
+
+000-2-1,50,24,0 script #knife NPC_KNIVES,{
+ .@q = getq(ShipQuests_Knife);
+ if (.@q) close;
+
+ mesn "Narrator";
+ mes col(l("There are some knives on the table. Would you like to take one?"), 9);
+ next;
+
+ menu
+ l("Yes."), L_Give,
+ l("No."), -;
+
+ closedialog;
+ close;
+
+L_Give:
+ mes "";
+ inventoryplace Knife, 1;
+
+ setq ShipQuests_Knife, 1;
+ getitem Knife, 1;
+
+ mesn "Narrator";
+ mes col(l("To open your inventory, use the F3 key or use your mouse to select it in the above menu in your client."), 9);
+ next;
+ mes col(l("When your inventory is open, you can equip an item by selecting it and clicking 'Equip'. You can do the same to unequip an item by clicking on 'Unequip'."), 9);
+ next;
+ mes col(l("Items have different effects. Some will heal you, some can be used as weapons or armor, and some can be sold for gold."), 9);
+
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-1/mapflags.txt b/npc/000-2-1/mapflags.txt
new file mode 100644
index 000000000..1543b585c
--- /dev/null
+++ b/npc/000-2-1/mapflags.txt
@@ -0,0 +1 @@
+000-2-1 mapflag town
diff --git a/npc/000-2-1/peter.txt b/npc/000-2-1/peter.txt
new file mode 100644
index 000000000..341087a23
--- /dev/null
+++ b/npc/000-2-1/peter.txt
@@ -0,0 +1,339 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Ablu
+// Alastrim
+// Qwerty Dragon
+// Reid
+// Vasily_Makarov
+// Description:
+// Rat hunter.
+// 4+2 bits array:
+// ShipQuests
+// Variable:
+// ShipQuests_Peter
+// Values:
+// 0 Doesn't know the quest.
+// 1 Task given.
+// 2 Task given and reward expected.
+// 3 Task completed without reward.
+// 4 Asked for reward after completion of the task.
+// 5 Task done and reward given.
+// 6 Did not start the quest.
+// Others:
+// .@peter = Peter variable.
+// "000-2-2" - map with mobs.
+// "$@RAT_SAILOR_HELPER$" - Name of the participant.
+// "$@RAT_SAILOR_DEATHS - Number of deaths when the participant starts the fight.
+// "$@RAT_SAILOR_CONTROL" - Explanation of each index of the array.
+// "$@RAT_SAILOR_OLD_HELPER$" - Name of the participant.
+// "$@RAT_SAILOR_COUNTDOWN" - Seconds since the epoch of when the player done the quest.
+// [1] = Shows status of ratto number 1 (1 is dead and 0 is alive).
+// [2] = Shows status of ratto number 2 (1 is dead and 0 is alive).
+// [3] = Shows status of ratto number 3 (1 is dead and 0 is alive).
+// [4] = Shows status of ratto number 4 (1 is dead and 0 is alive).
+// [5] = Shows how many seconds passed since ratto number 1 died.
+// [6] = Shows how many seconds passed since ratto number 2 died.
+// [7] = Shows how many seconds passed since ratto number 3 died.
+// [8] = Shows how many seconds passed since ratto number 4 died.
+// [9] = Shows how many seconds passed since the player started the quest.
+// [10] = Shows how many seconds passed since the player done the quest.
+
+000-2-1,72,34,0 script AreaNPC NPC_HIDDEN,0,1,{
+
+OnTouch:
+ if (BaseLevel < 5) goto L_Stop;
+ if ($@RAT_SAILOR_COUNTDOWN == 0) goto L_NoCountDown;
+ if ((gettimetick(2) - $@RAT_SAILOR_COUNTDOWN) < 10) goto L_NoGoodTick;
+ if (($@RAT_SAILOR_OLD_HELPER$ == strcharinfo(0)) && ((gettimetick(2) - $@RAT_SAILOR_COUNTDOWN) < 60)) goto L_NoGoodTick;
+ $@RAT_SAILOR_COUNTDOWN = 0;
+
+L_NoCountDown:
+ if ($@RAT_SAILOR_HELPER$ != "") goto L_Occupied;
+ .@peter = getq(ShipQuests_Peter);
+ if (.@peter < 1 || .@peter > 5) goto L_Task;
+ if (.@peter == 1 || .@peter == 2) goto L_Rfail;
+ if (.@peter == 3 || .@peter == 4) goto L_Rwin;
+ if (.@peter > 5) goto L_SecondTime;
+ doevent "Peter::OnReturnWin";
+ close;
+
+L_Stop:
+ doevent "Peter::OnStop";
+
+ close;
+
+L_Occupied:
+ doevent "Peter::OnDontneedHelp";
+
+ close;
+
+L_Task:
+ doevent "Peter::OnGiveTask";
+
+ close;
+
+L_Rfail:
+ doevent "Peter::OnReturnFail";
+
+ close;
+
+L_Rwin:
+ doevent "Peter::OnReturnWin";
+
+ close;
+
+L_NoGoodTick:
+ doevent "Peter::OnNoGoodTick";
+
+ close;
+}
+
+000-2-1,70,35,0 script Peter NPC_RATTO_SAILOR,{
+ if (BaseLevel < 5) goto OnTooWeak;
+ if ($@RAT_SAILOR_COUNTDOWN == 0) goto L_NoCountDown;
+ if ((gettimetick(2) - $@RAT_SAILOR_COUNTDOWN) < 10) goto OnNoGoodTick;
+ if (($@RAT_SAILOR_OLD_HELPER$ == strcharinfo(0)) && ((gettimetick(2) - $@RAT_SAILOR_COUNTDOWN) < 60)) goto OnNoGoodTick;
+ $@RAT_SAILOR_COUNTDOWN = 0;
+
+L_NoCountDown:
+ .@peter = getq(ShipQuests_Peter);
+ if (.@peter == 1 || .@peter == 2) goto OnReturnFail;
+ if (.@peter == 3 || .@peter == 4 || .@peter == 5) goto OnReturnWin;
+
+OnGiveTask:
+ setq ShipQuests_Peter, 6;
+ .@peter = getq(ShipQuests_Peter);
+ mesn;
+ mesq lg("Hey, girl!", "Hey, man!");
+ next;
+ mesq l("I need somebody who can rid the hold of the ship of these rattos. Can you help me?");
+ next;
+
+ menu
+ l("Yeah, but what reward will I get?"), L_BonusTask,
+ l("Why not, I need to train anyway."), L_Task,
+ l("No, they are way too dangerous for me!"), -;
+
+ mes "";
+ mesn;
+ mesq l("Hehe, hehe. Well, come back if you change your mind.");
+
+ goto L_Quit;
+
+OnTooWeak:
+ mesn;
+ mesq lg("I need someone to help me clean the edge of the ship, but you aren't strong enough for now.");
+
+ goto L_Quit;
+
+OnStop:
+ warp "000-2-1", 72, 36;
+
+ mesn;
+ mesq l("You can't go there!");
+
+ close;
+
+OnReturnFail:
+ mesn;
+ mesq l("I see it's not so easy to get rid of these rattos. Do you want to try again?");
+ next;
+
+ menu
+ l("Yeah, but I would like to make sure I get a reward."), L_BonusTask,
+ l("Why not, I need to train anyway."), L_Task,
+ l("No, they are way too dangerous for me!"), -;
+
+ mes "";
+ mesn;
+ mesq l("Hehe, hehe. Well, come back if you change your mind.");
+
+ goto L_Quit;
+
+OnReturnWin:
+ .@peter = getq(ShipQuests_Peter);
+ mesn;
+ mesq l("Thanks again for helping me. Drats these rattos for infesting our fair vessal!");
+ next;
+ mesq l("They are a permanent problem so I will always need your help to exterminate them in order to keep their number under control.");
+ next;
+ mesq l("Your help is very welcome indeed. Unfortunately, I can give you a reward for the first extermination only.");
+ next;
+
+ if (.@peter == 3 || .@peter == 4)
+ menu
+ l("Did you say reward? I want it!"), L_BonusTask,
+ l("I am not worried about rewards. I just want to help."), L_Task,
+ l("Sorry, I am not in the mood for another fight with these rattos."), -;
+
+ if (.@peter == 5)
+ menu
+ l("No problem, I can help you anyway."), L_Task,
+ l("Sorry, I am not in the mood for another fight with these rattos."), -;
+
+ mes "";
+ mesn;
+ mesq l("Hehe, hehe. Well, come back if you change your mind.");
+
+ close;
+
+L_BonusTask:
+ mes "";
+ mesn;
+ mesq l("What if I give you 1000 Esperin for that job, is it ok?");
+ next;
+
+ menu
+ lg("Okay, I'm ready to work!"), -,
+ l("What? This reward is too small!"), L_Quit;
+
+ .@peter = getq(ShipQuests_Peter);
+ if ($@RAT_SAILOR_HELPER$ != "") goto OnDontneedHelp;
+ if (.@peter == 6) setq ShipQuests_Peter, 2;
+ if (.@peter == 3) setq ShipQuests_Peter, 4;
+ .@peter = getq(ShipQuests_Peter);
+ goto L_Start;
+
+L_Task:
+ .@peter = getq(ShipQuests_Peter);
+ if ($@RAT_SAILOR_HELPER$ != "") goto OnDontneedHelp;
+ if (.@peter == 6) setq ShipQuests_Peter, 1;
+ .@peter = getq(ShipQuests_Peter);
+
+L_Start:
+ mes "";
+ mesn;
+ mesq l("Okay, you can start!");
+
+OnStartOutside:
+ if ($@RAT_SAILOR_HELPER$ != "") goto OnDontneedHelp;
+ $@RAT_SAILOR_HELPER$ = strcharinfo(0);
+ $@RAT_SAILOR_DEATHS = PC_DIE_COUNTER;
+ initnpctimer;
+ warp "000-2-2", 48, 28;
+ doevent "RattosControl::OnSpawn";
+
+ goto L_Quit;
+
+OnTimer2000:
+ if (attachrid(getcharid(3, $@RAT_SAILOR_HELPER$)) == 0) goto L_Logoff;
+ $@RAT_SAILOR_CONTROL[9] = $@RAT_SAILOR_CONTROL[9] + 2;
+ if ($@RAT_SAILOR_CONTROL[9] > 100) goto L_Timeout;
+ if (PC_DIE_COUNTER > $@RAT_SAILOR_DEATHS) goto L_Dead;
+ if ($@RAT_SAILOR_CONTROL[1] && $@RAT_SAILOR_CONTROL[2] && $@RAT_SAILOR_CONTROL[3] && $@RAT_SAILOR_CONTROL[4]) goto L_Done;
+ if (getmapusers("000-2-2") == 0) goto L_CleaningEnd;
+ goto L_CheckRattos;
+
+ end;
+
+L_CheckRattos:
+ if ($@RAT_SAILOR_CONTROL[1]) $@RAT_SAILOR_CONTROL[5] = $@RAT_SAILOR_CONTROL[5] + 2;
+ if ($@RAT_SAILOR_CONTROL[2]) $@RAT_SAILOR_CONTROL[6] = $@RAT_SAILOR_CONTROL[6] + 2;
+ if ($@RAT_SAILOR_CONTROL[3]) $@RAT_SAILOR_CONTROL[7] = $@RAT_SAILOR_CONTROL[7] + 2;
+ if ($@RAT_SAILOR_CONTROL[4]) $@RAT_SAILOR_CONTROL[8] = $@RAT_SAILOR_CONTROL[8] + 2;
+ if ($@RAT_SAILOR_CONTROL[5] > 45) doevent "RattosControl::OnRatto1Respawn";
+ if ($@RAT_SAILOR_CONTROL[6] > 45) doevent "RattosControl::OnRatto2Respawn";
+ if ($@RAT_SAILOR_CONTROL[7] > 45) doevent "RattosControl::OnRatto3Respawn";
+ if ($@RAT_SAILOR_CONTROL[8] > 45) doevent "RattosControl::OnRatto4Respawn";
+
+L_NotYet:
+ setnpctimer 0;
+
+ end;
+
+OnDontneedHelp:
+ mesn;
+ mesq l("I don't need your help right now, come back later.");
+ next;
+ mesq l("@@ is helping me.", $@RAT_SAILOR_HELPER$);
+
+ goto L_Quit;
+
+L_Timeout:
+ mesn;
+ mesq l("Hey! Be careful. You can't stay in this basement for so long, you're going to get sick. Come outside and take a break, maybe you can try again later.");
+ warp "000-2-1", 72, 36;
+
+ goto L_CleaningClose;
+
+L_Logoff:
+ goto L_CleaningEnd;
+
+L_Dead:
+// Warps the dead body outside, so it does not interfere with the getmapusers check.
+ if (getmapusers("000-2-2") > 0) warp "000-2-1", 72, 36;
+
+ goto L_CleaningEnd;
+
+L_Done:
+ $@RAT_SAILOR_CONTROL[10] = $@RAT_SAILOR_CONTROL[10] + 2;
+ if($@RAT_SAILOR_CONTROL[10] < 5) goto L_NotYet;
+ .@peter = getq(ShipQuests_Peter);
+ if (.@peter == 2 || .@peter == 4) goto L_Reward;
+ warp "000-2-1", 72, 36;
+
+ goto L_Thanks;
+
+L_CleaningEnd:
+ stopnpctimer;
+ $@RAT_SAILOR_HELPER$ = "";
+ $@RAT_SAILOR_DEATHS = 0;
+ cleararray $@RAT_SAILOR_CONTROL, 0, 11;
+ killmonster "000-2-2", "RattosControl::OnRatto1Death";
+ killmonster "000-2-2", "RattosControl::OnRatto2Death";
+ killmonster "000-2-2", "RattosControl::OnRatto3Death";
+ killmonster "000-2-2", "RattosControl::OnRatto4Death";
+
+ end;
+
+L_CleaningClose:
+ stopnpctimer;
+ $@RAT_SAILOR_OLD_HELPER$ = $@RAT_SAILOR_HELPER$;
+ $@RAT_SAILOR_HELPER$ = "";
+ $@RAT_SAILOR_DEATHS = 0;
+ cleararray $@RAT_SAILOR_CONTROL, 0, 11;
+ killmonster "000-2-2", "RattosControl::OnRatto1Death";
+ killmonster "000-2-2", "RattosControl::OnRatto2Death";
+ killmonster "000-2-2", "RattosControl::OnRatto3Death";
+ killmonster "000-2-2", "RattosControl::OnRatto4Death";
+ $@RAT_SAILOR_COUNTDOWN = gettimetick(2);
+
+ close;
+
+L_Reward:
+ warp "000-2-1", 72, 36;
+ setq ShipQuests_Peter, 5;
+ .@peter = getq(ShipQuests_Peter);
+ mesn;
+ mesq l("Good job!") + " " + l("Here's your reward!");
+ getexp 100, 0;
+ Zeny = Zeny + 1000;
+ message strcharinfo(0), l("You receive @@ E!", 1000);
+
+ goto L_CleaningClose;
+
+L_Thanks:
+ mesn;
+ mesq l("Thanks for helping me!");
+ .@peter = getq(ShipQuests_Peter);
+ if (.@peter == 1) setq ShipQuests_Peter, 3;
+ .@peter = getq(ShipQuests_Peter);
+
+ goto L_CleaningClose;
+
+L_Quit:
+ .@peter = 0;
+
+ close;
+
+OnNoGoodTick:
+ mesn;
+ mesq l("I don't need your help right now, come back later.");
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
diff --git a/npc/000-2-1/q'onan.txt b/npc/000-2-1/q'onan.txt
new file mode 100644
index 000000000..bee4f34a9
--- /dev/null
+++ b/npc/000-2-1/q'onan.txt
@@ -0,0 +1,16 @@
+// Evol scripts.
+// Authors:
+// Alige
+// Vasily_Makarov
+// Description:
+// Sleeping and snoring NPC.
+
+000-2-1,53,38,0 script Q'Onan#000-2-1 NPC_ORC_SAILOR,{
+ asleep;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-1/story_save.txt b/npc/000-2-1/story_save.txt
new file mode 100644
index 000000000..44171ad62
--- /dev/null
+++ b/npc/000-2-1/story_save.txt
@@ -0,0 +1,30 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Scritpted save locations in 000-2-1 map.
+
+000-2-1,50,38,0 script #name3 NPC_FINAL_POINT,{
+ .@q_nard = getq(ShipQuests_Nard);
+ .@q_narr = getq(General_Narrator);
+
+ if(.@q_nard == 5 && .@q_narr < 1)
+ {
+OnClick:
+ narrator S_LAST_NEXT,
+ l("You lie in the bed."),
+ l("Your head is suddently heavy, your eyes are closing..."),
+ lg("You fell asleep.");
+
+ warp "000-0-1", 26, 28;
+ }
+ else
+ {
+ savepointparticle "000-2-1", 50, 38;
+ }
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-2/_import.txt b/npc/000-2-2/_import.txt
new file mode 100644
index 000000000..81d32fdfb
--- /dev/null
+++ b/npc/000-2-2/_import.txt
@@ -0,0 +1,5 @@
+// Map 000-2-2: Hold
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/000-2-2/doors.txt",
+"npc/000-2-2/mapflags.txt",
+"npc/000-2-2/ratto.txt",
diff --git a/npc/000-2-2/doors.txt b/npc/000-2-2/doors.txt
new file mode 100644
index 000000000..1dbef8328
--- /dev/null
+++ b/npc/000-2-2/doors.txt
@@ -0,0 +1,69 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Alastrim
+// Reid
+// Description:
+// Doors NPCs.
+
+000-2-2,48,29,0 script DoorUpwards NPC_HIDDEN,0,0,{
+
+OnTouch:
+ if (mobcount("000-2-2","all") > 0) goto L_Warn;
+
+ goto L_Warp;
+
+L_Warn:
+ .@q = getq(ShipQuests_Peter);
+ if (.@q == 5) goto L_Warp;
+
+ mesn "Narrator";
+ mes col(l("There are still some rattos left! Do you want to abort the quest?"), 9);
+ next;
+
+ menu
+ l("Yes."), L_Warp,
+ l("No."), -;
+
+ warp "000-2-2", 48, 28;
+ closedialog;
+ close;
+
+L_Warp:
+ warp "000-2-1", 72, 36;
+ closedialog;
+ close;
+}
+
+000-2-2,24,31,0 script LeftDoor NPC_HIDDEN,0,0,{
+
+OnTouch:
+ mesn "Narrator";
+ mes col(l("It seems that you need a key to open this door."), 9);
+ next;
+ mes col(l("What do you want to do?"), 9);
+ next;
+
+ menu
+ rif(countitem(718) > 0, l("Use the key.")), L_Warp,
+ l("Break the door."), L_Break,
+ l("Go away."), -;
+
+ closedialog;
+ close;
+
+L_Break:
+
+ mes "";
+ mesn "Narrator";
+ mes col(l("You hear a loud scream. It must be the creaking of the wooden door..."), 9);
+
+ close;
+
+L_Warp:
+ mes "";
+ mesn "Narrator";
+ mes col(l("Wait, it seems someone is blocking the door from the other side!"), 9);
+
+ close;
+}
diff --git a/npc/000-2-2/mapflags.txt b/npc/000-2-2/mapflags.txt
new file mode 100644
index 000000000..5202b3321
--- /dev/null
+++ b/npc/000-2-2/mapflags.txt
@@ -0,0 +1 @@
+000-2-2 mapflag nosave 000-2-1,50,38
diff --git a/npc/000-2-2/ratto.txt b/npc/000-2-2/ratto.txt
new file mode 100644
index 000000000..1392d5716
--- /dev/null
+++ b/npc/000-2-2/ratto.txt
@@ -0,0 +1,68 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Alastrim
+// Reid
+// Description:
+// Ratto killer.
+
+// $@RAT_SAILOR_CONTROL array explanation:
+// [1] = Shows status of ratto number 1 (1 is dead and 0 is alive).
+// [2] = Shows status of ratto number 2 (1 is dead and 0 is alive).
+// [3] = Shows status of ratto number 3 (1 is dead and 0 is alive).
+// [4] = Shows status of ratto number 4 (1 is dead and 0 is alive).
+// [5] = Shows how many seconds passed since ratto number 1 died.
+// [6] = Shows how many seconds passed since ratto number 2 died.
+// [7] = Shows how many seconds passed since ratto number 3 died.
+// [8] = Shows how many seconds passed since ratto number 4 died.
+// [9] = Shows how many seconds passed since the player started the quest.
+
+000-2-2,47,30,0 script RattosControl NPC_HIDDEN,{
+
+OnSpawn:
+ areamonster "000-2-2", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl::OnRatto1Death";
+ areamonster "000-2-2", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl::OnRatto2Death";
+ areamonster "000-2-2", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl::OnRatto3Death";
+ areamonster "000-2-2", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl::OnRatto4Death";
+ close;
+
+OnRatto1Respawn:
+ areamonster "000-2-2", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl::OnRatto1Death";
+ $@RAT_SAILOR_CONTROL[1] = 0;
+ $@RAT_SAILOR_CONTROL[5] = 0;
+ end;
+
+OnRatto2Respawn:
+ areamonster "000-2-2", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl::OnRatto2Death";
+ $@RAT_SAILOR_CONTROL[2] = 0;
+ $@RAT_SAILOR_CONTROL[6] = 0;
+ end;
+
+OnRatto3Respawn:
+ areamonster "000-2-2", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl::OnRatto3Death";
+ $@RAT_SAILOR_CONTROL[3] = 0;
+ $@RAT_SAILOR_CONTROL[7] = 0;
+ end;
+
+OnRatto4Respawn:
+ areamonster "000-2-2", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl::OnRatto4Death";
+ $@RAT_SAILOR_CONTROL[4] = 0;
+ $@RAT_SAILOR_CONTROL[8] = 0;
+ end;
+
+OnRatto1Death:
+ $@RAT_SAILOR_CONTROL[1] = 1;
+ end;
+
+OnRatto2Death:
+ $@RAT_SAILOR_CONTROL[2] = 1;
+ end;
+
+OnRatto3Death:
+ $@RAT_SAILOR_CONTROL[3] = 1;
+ end;
+
+OnRatto4Death:
+ $@RAT_SAILOR_CONTROL[4] = 1;
+ end;
+}
diff --git a/npc/000-2-3/_import.txt b/npc/000-2-3/_import.txt
new file mode 100644
index 000000000..16842f77b
--- /dev/null
+++ b/npc/000-2-3/_import.txt
@@ -0,0 +1,10 @@
+// Map 000-2-3: Nard's Room
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/000-2-3/_warps.txt",
+"npc/000-2-3/box.txt",
+"npc/000-2-3/elmo.txt",
+"npc/000-2-3/hammock.txt",
+"npc/000-2-3/mapflags.txt",
+"npc/000-2-3/nard.txt",
+"npc/000-2-3/piourocket.txt",
+"npc/000-2-3/sailors.txt",
diff --git a/npc/000-2-3/_warps.txt b/npc/000-2-3/_warps.txt
new file mode 100644
index 000000000..f5c0e1e70
--- /dev/null
+++ b/npc/000-2-3/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-2-3: Nard's Room warps
+000-2-3,19,27,0 warp #000-2-3_19_27 0,0,000-2-0,32,28
diff --git a/npc/000-2-3/box.txt b/npc/000-2-3/box.txt
new file mode 100644
index 000000000..cc280b746
--- /dev/null
+++ b/npc/000-2-3/box.txt
@@ -0,0 +1,112 @@
+// Evol scripts.
+// Authors:
+// Qwerty Dragon
+// Reid
+// Description:
+// Captain Nard dialogs.
+// Nard does the introduction with a small quest.
+// This quest is meant to teach the player how to use a weapon,and to bring food to the ship.
+// 4 bits array:
+// ShipQuests
+// Variable:
+// ShipQuests_Nard
+// Values:
+// 0 Introduction of the boxes and Nard. This is displayed when the player never spoke to Nard or his box.
+// 1 Nard spoke and gave access to the outdoor of the ship.
+// 2 Completed the Gugli quest.
+// 3 ChefGado Quest accepted.
+// 4 ChefGado Quest completed and "Introduction" chapter finalized.
+// 5 Reward taken from the box.
+
+000-2-3,25,24,0 script Box NPC_HAT_BOX,{
+ .@q = getq(ShipQuests_Nard);
+
+ mesn "Narrator";
+ mes col(l("Some Bandanas and Sailor Hats are inside this box."), 9);
+ next;
+ mes col(l("What do you wish to do?"), 9);
+ next;
+
+ menu
+ l("Take a Bandana."), -,
+ l("Nothing."), L_Quit;
+
+ if (.@q == 0) goto L_NoQuest;
+ if (.@q == 4) goto L_Give;
+ if (.@q > 4) goto L_Already;
+
+ setcamnpc "Nard";
+ mes "";
+ mesn "Nard";
+ mesq l("Please don't touch these hats, they are for crew members only.");
+
+ close;
+
+L_NoQuest:
+ mes "";
+ mesn "Narrator";
+ mes col(l("Nard looks surprised and stops you."), 9);
+ next;
+
+ setcamnpc "Nard";
+ mesn "Nard";
+ mesq l("You like these hats, right?");
+ next;
+ mesq l("How about I ask you to help the crew? It would mean that you're one of us and that you will be able to get one of these hats.");
+ next;
+ mesq l("We need as many hands as possible to explore the island out there, and to get some new food.");
+ next;
+ mesq l("You could meet some of the other sailors this way, and... Getting this hat of course, will be a sign of you becoming part of our crew.");
+ next;
+ mesq l("What do you think?");
+ next;
+
+ menu
+ l("Why not, I've got plenty of free time."), -,
+ l("I think that I'm still a bit sick."), L_Quit;
+
+ mes "";
+ mesn "Nard";
+ mesq l("Great!");
+ next;
+ mesq l("I give you this key, it opens all the doors on this ship.");
+ next;
+ mesq l("Now go outside and talk with Gugli, he'll tell you what provisions we need.");
+ next;
+
+ inventoryplace JohanneKey, 1;
+ setq ShipQuests_Nard, 1;
+ getitem JohanneKey, 1;
+
+ close;
+
+L_Give:
+ setcamnpc "Nard";
+ mes "";
+ mesn "Nard";
+ mesq l("Congrats, you are now part of the crew. Thanks again for your help.");
+
+ inventoryplace Bandana, 1;
+
+ setq ShipQuests_Nard, 5;
+ getitem Bandana, 1;
+// Need to add a skill for the crew at this line.
+
+ close;
+
+L_Already:
+ setcamnpc "Nard";
+ mes "";
+ mesn "Nard";
+ mesq l("You already took a @@, please put this one back in the box.", getitemlink(Bandana));
+
+ close;
+
+L_Quit:
+ closedialog;
+ close;
+
+OnInit:
+ .distance = 1;
+ end;
+}
diff --git a/npc/000-2-3/elmo.txt b/npc/000-2-3/elmo.txt
new file mode 100644
index 000000000..c623e3215
--- /dev/null
+++ b/npc/000-2-3/elmo.txt
@@ -0,0 +1,67 @@
+// Evol scripts.
+// Authors:
+// Qwerty Dragon
+// Reid
+// Description:
+// Elmo's second dialog.
+
+000-2-3,27,27,0 script Elmo NPC_ELMO,{
+ function got_money {
+ speech S_LAST_NEXT,
+ lg("Be patient a little while longer, in the next few days we will arrive at the port of Artis..."),
+ l("If you feel bored or like running around in circles, you may want to talk with the other sailors around here to get some tasks to do."),
+ l("From what I heard, my brother Gugli needs the help of as many people as possible in order to collect a lot of neat things that can be found on this island."),
+ l("Other than that, I don't know much about what else is going on, so directly asking the Cap'tain about it could be a good idea.");
+
+ goodbye;
+ }
+
+ if (getq(General_Narrator) > 0)
+ {
+ sailortalk;
+ }
+
+ if (getq(ShipQuests_ArpanMoney) == 2)
+ {
+ got_money;
+ }
+
+ speech S_LAST_NEXT,
+ l("Hey you, sorry for leaving your room so quickly. I needed to speak with the captain about the food reserves. You know, now that we have a new mouth to feed, we need to check what we have."),
+ l("So, how is it going? Did you meet any other crew members yet?");
+
+ switch (select(l("Yes, Arpan gave me these clothes."), l("Not yet.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh good! Did he give you your money back as well?");
+
+ switch (select(l("Yes he did."), l("He told me nothing about that.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Ok, be patient a little while longer, in the next few days we will arrive at the port of Artis...");
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Hehe, sometimes he gets his head in the clouds, You should go ask him about that.");
+ setq ShipQuests_ArpanMoney, 1;
+ break;
+ }
+
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You should go see them."),
+ l("You still got a few days before we arrive at the port, maybe you can learn something from them?");
+
+ break;
+ }
+
+ goodbye;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 5;
+ end;
+}
diff --git a/npc/000-2-3/hammock.txt b/npc/000-2-3/hammock.txt
new file mode 100644
index 000000000..0ceeadbff
--- /dev/null
+++ b/npc/000-2-3/hammock.txt
@@ -0,0 +1,17 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Animated hammock at the top level of the ship.
+
+000-2-3,28,24,0 script #name5 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchRight;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
diff --git a/npc/000-2-3/mapflags.txt b/npc/000-2-3/mapflags.txt
new file mode 100644
index 000000000..b04a0fc96
--- /dev/null
+++ b/npc/000-2-3/mapflags.txt
@@ -0,0 +1 @@
+000-2-3 mapflag town
diff --git a/npc/000-2-3/nard.txt b/npc/000-2-3/nard.txt
new file mode 100644
index 000000000..86dbe50a2
--- /dev/null
+++ b/npc/000-2-3/nard.txt
@@ -0,0 +1,277 @@
+// Evol scripts.
+// Authors:
+// Qwerty Dragon
+// Reid
+// Description:
+// Captain Nard dialogs.
+// Nard does the introduction with a small quest.
+// This quest is meant to teach the player how to use a weapon,and to bring food to the ship.
+// 4 bits array:
+// ShipQuests
+// Variable:
+// 0 ShipQuests_Nard
+// 1 ShipQuests_Gugli
+// 2 ShipQuests_ChefGado
+// Values:
+// 00 Introduction of the boxes and Nard. This is displayed when the player never spoke to Nard or his box.
+// 01 Nard spoke and gave access to the outdoor of the ship.
+// 02 Completed the Gugli quest.
+// 03 ChefGado Quest accepted.
+// 04 ChefGado Quest completed and "Introduction" chapter finalized.
+// 05 Reward taken from the box.
+// 06 Intro finished
+// 10 Never talked with Gugli.
+// 11 Gugli gives you the task.
+// 12 Gave all of the boxes to Gugli.
+
+000-2-3,25,26,0 script Nard NPC_NARD,{
+ .@nard = getq(ShipQuests_Nard);
+ .@gugli = getq(ShipQuests_Gugli);
+ .@gado = getq(ShipQuests_ChefGado);
+
+L_Checker:
+ if (.@gado > 3 && .@nard == 3) goto L_ChefQuestComplete;
+ if (.@nard == 2) goto L_ChefQuestStart;
+ if (.@nard == 3) goto L_ChefQuestGiven;
+ if (.@nard == 4) goto L_Reward;
+ if (.@nard > 5) goto L_GoBackArtis;
+ if (.@nard > 4) goto L_Already;
+ if (.@gugli == 2) goto L_Done;
+ if (.@nard == 1) goto L_NotYet;
+
+ mesn;
+ mesq l("Hello.");
+ next;
+ mesq l("Let me introduce myself, I am Nard, captain of this ship.");
+ next;
+ mesq lg("I am pleased to see that you have woken up and are active. Elmo came here to tell me this good news!");
+ next;
+
+ setcamnpc "Elmo";
+ mesn "Elmo";
+ mesq l("Oh... Err, yes I did, or, well, good day to you!");
+ next;
+ restorecam;
+
+ mesn;
+ mesq l("Hehehe, he is a bit nervous, please forgive him, it is not everyday we have a new member in the crew!");
+ next;
+ mesq l("So, how do you feel? I see that Julia did a marvelous job! You look like you're in good health now.");
+ next;
+
+L_Menu:
+ menu
+ lg("I feel ok."), L_Ok,
+ l("Who's this Julia?"), L_Julia,
+ lg("I'm a bit sick..."), -;
+
+ mes "";
+ mesn;
+ mesq l("Oh, I was going to ask you if you wanted to help the crew search for some food and explore the island out there.");
+ next;
+
+L_MenuQuest:
+ menu
+ l("What do you need?"), -,
+ l("Is there a reward?"), L_NeedHead,
+ l("Wait, you never came here before?"), L_DrasilIsland;
+
+ mes "";
+ mesn;
+ mesq l("Oh! I like that sort of answer!");
+ next;
+ mesq lg("We need manpower on the island... Oh forgive me, women are also welcome, of course.", "We need manpower on the island.");
+ next;
+
+ goto L_NeedContent;
+
+L_NeedHead:
+ mes "";
+ mesn;
+ mesq l("Of course there is a reward for your task.");
+ next;
+ mesq l("Hard work always pays off!");
+ next;
+ mesq l("What? It's not good enough?");
+ next;
+
+L_NeedContent:
+ mesq l("Our crew is like a family, and if you agree to help us, I would like to invite you to join our family!");
+ next;
+ mesq l("Hmm, I'll also give you one of these hats from the box near you, but only after you complete your task!");
+ next;
+ mesq l("Here, take this key, it opens all the doors on this ship.");
+ next;
+ mesq l("Now go outside and talk to Gugli, he'll tell you what we need.");
+ next;
+
+ inventoryplace JohanneKey, 1;
+
+ setq ShipQuests_Nard, 1;
+ getitem JohanneKey, 1;
+
+ close;
+
+L_Ok:
+ mes "";
+ mesn;
+ mesq l("Good to know.");
+ next;
+ mesq l("We have made a stop at a little island, before making it on to the port of Artis.");
+ next;
+ mesq l("It would be good for you to do some exercise, the ship isn't big enough for that.");
+ next;
+
+ goto L_SpecialTask;
+
+L_Julia:
+ mes "";
+ mesn;
+ mesq l("You have an awful case of amnesia.");
+ next;
+ mesq l("She is the nurse and shipkeeper of this ship.");
+ next;
+ mesq lg("But most important, she is the one who took care of you when you were unconscious.");
+ next;
+
+L_SpecialTask:
+ mesq l("I know that you are just starting to feel better, but I'd like to give you a special task.");
+ next;
+
+ goto L_MenuQuest;
+
+L_DrasilIsland:
+ mes "";
+ mesn;
+ mesq l("To be honest, no, never.");
+ next;
+ mesq l("But discovering new territories is probably the best thing that can happen to sailors, don't you think?");
+ next;
+ mesq l("I'm really excited, this place reminds me of an ancient mythical tree, you might know what I'm talking about...");
+ emotion E_WINK;
+ next;
+ mesq l("As captain of this ship, I officially name this newly discovered land the ##BDrasil Island##b!");
+ next;
+ mesq l("Now, lets get back to business.");
+ next;
+
+ goto L_NeedContent;
+
+L_NotYet:
+ mesn;
+ mesq l("You still haven't completed your tasks.");
+ close;
+
+L_Done:
+ mesn;
+ mesq l("Hi @@.", strcharinfo(0));
+ next;
+ mesq l("Elmo and Gugli told me that you did all of the tasks outside, congrats!");
+
+ setq ShipQuests_Nard, 2;
+ next;
+ goto L_ChefQuestRedir;
+
+L_ChefQuestStart:
+ mesn;
+ mesq lg("Elmo told me you are now considered family and are numbered among us in our activities on the island. I do so very much appreciate the efforts you did down there.");
+ next;
+
+L_ChefQuestRedir:
+ mesq l("Unfortunately, we still need help from you. This time it will be a delicate task, here onboard.");
+ next;
+ mesq l("Elmo brought reports to me about some frictions between my old and new lieutenants. You probably already met Julia and Chef Gado.");
+ next;
+ mesq l("They are each valued individuals and I need them both. In the past, I probably made my share of mistakes. I regret good management is so difficult. I was wondering if you could investigate and... Sort out this situation.");
+ next;
+
+ select
+ l("Of the two of them, who has 'good' on their side?");
+
+ mes "";
+ mesq l("I do not want to go pointing my finger at someone. I want to be honorable and fair, and I sense the same quality in you, so I put my trust in you. I am sure you will be able to judge and solve this troubling situation.");
+
+ setq ShipQuests_Nard, 3;
+
+ close;
+
+L_ChefQuestGiven:
+ mesn;
+ mesq l("It seems you still have some work to do.");
+
+ close;
+
+L_ChefQuestComplete:
+ mesn;
+ mesq l("Congratulations!");
+ next;
+ mesq l("You are now officially part of my crew! Thanks again for your help.");
+ next;
+ mesq l("Take your reward from the box next to my desk!");
+ next;
+
+ select
+ l("I will take it! Thank you captain!");
+
+ setq ShipQuests_Nard, 4;
+ getexp 50, 0;
+
+// Need to add a skill for the crew at this line.
+ mes "";
+
+L_Already:
+ speech
+ l("I recommend you to take a nap on the inferior level, we will soon leave this place.");
+
+ close;
+
+L_GoBackArtis:
+ checkclientversion;
+ speech S_LAST_NEXT,
+ l("Enough of this island?"),
+ l("Where would you like to go now?");
+ switch (select(l("Let's go to Artis."),
+ l("Tell me, where are we right now?"),
+ l("I would like to stay here a bit more.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Let's set sail then!");
+
+ savepoint "001-2-22", 50, 38;
+ if (!getmapxy(.@map$, .@x, .@y, 0))
+ {
+ warp "001-2-24", .@x, .@y;
+ }
+ else
+ {
+ warp "001-2-24", 22, 27;
+ }
+
+ closedialog;
+ close;
+
+ case 2:
+ closedialog;
+ npctalk3 l("This is Drasil Island, I named it after an ancient mythical tree.");
+ close;
+
+ case 3:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Ok I stay here with my paperwork if you need my help.");
+
+ closedialog;
+ close;
+ }
+
+L_Reward:
+ mesn;
+ mesq l("Hey! There's a reward for you in the box next to me!");
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 5;
+ end;
+}
diff --git a/npc/000-2-3/piourocket.txt b/npc/000-2-3/piourocket.txt
new file mode 100644
index 000000000..e6ff2039e
--- /dev/null
+++ b/npc/000-2-3/piourocket.txt
@@ -0,0 +1,29 @@
+// Evol scripts.
+// Author:
+// Ablu
+// Description:
+// Jumping piou.
+
+000-2-3,27,23,4 script #piourocket NPC_PIOU_ROCKET,{
+
+ .@now = gettimetick(2);
+
+ if (.@now - .last > 1)
+ {
+ .dir = 2;
+ .last = .@now;
+ specialeffect(26);
+ initnpctimer;
+ }
+
+ close;
+
+OnTimer1420:
+ .dir = 4;
+ stopnpctimer;
+ end;
+
+OnInit:
+ .distance = 3;
+ end;
+}
diff --git a/npc/000-2-3/sailors.txt b/npc/000-2-3/sailors.txt
new file mode 100644
index 000000000..968d8c92a
--- /dev/null
+++ b/npc/000-2-3/sailors.txt
@@ -0,0 +1,47 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Qwerty Dragon
+// Reid
+// Description:
+// End of introduction with Nard and Elmo talking about the player.
+
+000-2-3,21,28,0 script AreaTop NPC_HIDDEN,0,5,{
+
+OnTouch:
+ if (getq(ShipQuests_Door) == 1) end;
+ setq ShipQuests_Door, 1;
+
+ setcamnpc "Elmo";
+ mesn "Elmo";
+ mesq lg("So that's why we wanted to warn you, maybe she comes from that guild, as that sign was on her raft.", "So that's why we wanted to warn you, maybe he comes from that guild, as that sign was on his raft.");
+ next;
+
+ setcamnpc "Nard";
+ mesn "Captain Nard";
+ mesq lg("I see. Warn the other sailors about this. But if she's part of the Legion of Aemil, then she's also our friend and ally.", "I see. Warn the other sailors about this. But if he's part of the Legion of Aemil, then he's also our friend and ally.");
+ next;
+
+ setcamnpc "Elmo";
+ mesn "Elmo";
+ mesq l("I will.");
+ next;
+ mesq l("About the Legion of Aemil, I'm not sure about them, frankly.");
+ next;
+ mesq l("There are rumors going around that they did some monstrous things and that they are hiding quite a lot from us.");
+ next;
+
+ setcamnpc "Nard";
+ mesn "Captain Nard";
+ mesq lg("This kind of talk should be taken with a grain of salt, but I agree and admit that I too am skeptical, so keep an eye on her.", "This kind of talk should be taken with a grain of salt, but I agree and admit that I too am skeptical, so keep an eye on him.");
+ next;
+
+ mesq lg("But... If she has amnesia like Julia said... We don't need to worry about her. At least not yet.", "But... If he has amnesia like Julia said... We don't need to worry about him. At least not yet.");
+ next;
+
+ setcamnpc "Elmo";
+ mesn "Elmo";
+ mesq l("Sure, cap'tain.");
+
+ close;
+}
diff --git a/npc/000-2-4/_import.txt b/npc/000-2-4/_import.txt
new file mode 100644
index 000000000..579e400ac
--- /dev/null
+++ b/npc/000-2-4/_import.txt
@@ -0,0 +1,6 @@
+// Map 000-2-4: Alige's Hiding Place
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/000-2-4/_mobs.txt",
+"npc/000-2-4/_warps.txt",
+"npc/000-2-4/alige.txt",
+"npc/000-2-4/mapflags.txt",
diff --git a/npc/000-2-4/_mobs.txt b/npc/000-2-4/_mobs.txt
new file mode 100644
index 000000000..56230670e
--- /dev/null
+++ b/npc/000-2-4/_mobs.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-2-4: Alige's Hiding Place mobs
+000-2-4,30,30,1,1 monster Cuco 1020,1,80000,90000
diff --git a/npc/000-2-4/_warps.txt b/npc/000-2-4/_warps.txt
new file mode 100644
index 000000000..adfe94409
--- /dev/null
+++ b/npc/000-2-4/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-2-4: Alige's Hiding Place warps
+000-2-4,41,30,0 warp #000-2-4_41_30 0,0,000-2-2,25,31
diff --git a/npc/000-2-4/alige.txt b/npc/000-2-4/alige.txt
new file mode 100644
index 000000000..fbfb79eeb
--- /dev/null
+++ b/npc/000-2-4/alige.txt
@@ -0,0 +1,39 @@
+// Evol scripts.
+// Authors:
+// Reid
+// Travolta
+
+000-2-4,38,22,0 script Alige#000-2-4 NPC_ALIGE_BARREL,2,2,{
+ npctalk3 l("Protect me, please...");
+ end;
+
+OnTouch:
+ .dir = LEFT;
+ stopnpctimer;
+ initnpctimer;
+ end;
+
+OnUnTouch:
+ .dir = UP;
+ stopnpctimer;
+ initnpctimer;
+ end;
+
+OnTimer190:
+ switch (.dir)
+ {
+ case UP:
+ .dir = DOWN;
+ break;
+ case LEFT:
+ .dir = RIGHT;
+ break;
+ }
+ stopnpctimer;
+ end;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/000-2-4/mapflags.txt b/npc/000-2-4/mapflags.txt
new file mode 100644
index 000000000..9c0339379
--- /dev/null
+++ b/npc/000-2-4/mapflags.txt
@@ -0,0 +1 @@
+000-2-4 mapflag nosave 000-2-1,50,38
diff --git a/npc/001-1/_import.txt b/npc/001-1/_import.txt
new file mode 100644
index 000000000..08a4104c4
--- /dev/null
+++ b/npc/001-1/_import.txt
@@ -0,0 +1,42 @@
+// Map 001-1: Artis
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-1/_mobs.txt",
+"npc/001-1/_warps.txt",
+"npc/001-1/apana.txt",
+"npc/001-1/artaxe.txt",
+"npc/001-1/beuss.txt",
+"npc/001-1/calypsan.txt",
+"npc/001-1/carmie.txt",
+"npc/001-1/chelios.txt",
+"npc/001-1/cookiemaster.txt",
+"npc/001-1/devis.txt",
+"npc/001-1/doors.txt",
+"npc/001-1/elmo.txt",
+"npc/001-1/enora.txt",
+"npc/001-1/eugene.txt",
+"npc/001-1/fexil.txt",
+"npc/001-1/flyingpiou.txt",
+"npc/001-1/harbours.txt",
+"npc/001-1/juscare.txt",
+"npc/001-1/katja.txt",
+"npc/001-1/lucas.txt",
+"npc/001-1/manhole.txt",
+"npc/001-1/mapflags.txt",
+"npc/001-1/merlin.txt",
+"npc/001-1/mouboo.txt",
+"npc/001-1/nalkri.txt",
+"npc/001-1/panels.txt",
+"npc/001-1/pious.txt",
+"npc/001-1/qonan.txt",
+"npc/001-1/qpid.txt",
+"npc/001-1/rumly.txt",
+"npc/001-1/salem.txt",
+"npc/001-1/shop.txt",
+"npc/001-1/sign.txt",
+"npc/001-1/taree.txt",
+"npc/001-1/treeleaf.txt",
+"npc/001-1/trees.txt",
+"npc/001-1/wateranimation.txt",
+"npc/001-1/xilaxa.txt",
+"npc/001-1/karim.txt",
+"npc/001-1/hinnack.txt", \ No newline at end of file
diff --git a/npc/001-1/_mobs.txt b/npc/001-1/_mobs.txt
new file mode 100644
index 000000000..a2b6e5f1a
--- /dev/null
+++ b/npc/001-1/_mobs.txt
@@ -0,0 +1,32 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-1: Artis mobs
+001-1,0,0,0,0 monster Piou 1002,2,15000,60000
+001-1,0,0,0,0 monster Piousse 1003,1,15000,150000
+001-1,174,34,11,15 monster Fluffy 1022,6,18000,100000
+001-1,199,48,2,5 monster Fluffy 1022,4,18000,100000
+001-1,174,34,11,15 monster Piou 1002,1,12000,60000
+001-1,35,62,1,4 monster Pikpik 1013,3,40000,20000
+001-1,26,96,3,2 monster Pikpik 1013,1,40000,20000
+001-1,42,137,4,1 monster Pikpik 1013,2,40000,20000
+001-1,45,136,0,0 monster Crocotree 1010,1,420000,240000
+001-1,70,136,0,0 monster Crocotree 1010,1,420000,240000
+001-1,37,126,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,34,130,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,41,129,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,36,77,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,37,79,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,39,73,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,43,70,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,48,71,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,40,67,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,46,65,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,152,26,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,152,32,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,155,37,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,158,29,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,203,51,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,198,50,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,199,55,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,185,65,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,191,63,0,0 monster Manana Tree 1017,1,420000,240000
+001-1,200,66,0,0 monster Manana Tree 1017,1,420000,240000
diff --git a/npc/001-1/_warps.txt b/npc/001-1/_warps.txt
new file mode 100644
index 000000000..90a7dc1f8
--- /dev/null
+++ b/npc/001-1/_warps.txt
@@ -0,0 +1,445 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-1: Artis warps
+001-1,51,80,0 script #001-1_51_80_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-4", 48, 40;
+close;
+
+OnUnTouch:
+ doevent "#001-1_51_80::OnUnTouch";
+}
+001-1,51,80,0 script #001-1_51_80 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,70,77,0 script #001-1_70_77_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-2", 38, 38;
+close;
+
+OnUnTouch:
+ doevent "#001-1_70_77::OnUnTouch";
+}
+001-1,70,77,0 script #001-1_70_77 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,51,65,0 script #001-1_51_65_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-0", 30, 34;
+close;
+
+OnUnTouch:
+ doevent "#001-1_51_65::OnUnTouch";
+}
+001-1,51,65,0 script #001-1_51_65 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,55,71,0 script #001-1_55_71_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-0", 37, 45;
+close;
+
+OnUnTouch:
+ doevent "#001-1_55_71::OnUnTouch";
+}
+001-1,55,71,0 script #001-1_55_71 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,168,98,0 script #001-1_168_98_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-16", 32, 35;
+close;
+
+OnUnTouch:
+ doevent "#001-1_168_98::OnUnTouch";
+}
+001-1,168,98,0 script #001-1_168_98 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,194,109,0 warp #001-1_194_109 0,0,001-2-21,20,28
+001-1,100,37,0 warp #001-1_100_37 0,0,001-2-19,32,39
+001-1,104,43,0 warp #001-1_104_43 0,0,001-2-19,41,49
+001-1,134,83,0 warp #001-1_134_83 0,0,001-2-28,60,31
+001-1,118,88,0 script #001-1_118_88_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-28", 29, 42;
+close;
+
+OnUnTouch:
+ doevent "#001-1_118_88::OnUnTouch";
+}
+001-1,118,88,0 script #001-1_118_88 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,182,74,0 script #001-1_182_74_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-18", 39, 35;
+close;
+
+OnUnTouch:
+ doevent "#001-1_182_74::OnUnTouch";
+}
+001-1,182,74,0 script #001-1_182_74 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,163,70,0 script #001-1_163_70_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-26", 28, 42;
+close;
+
+OnUnTouch:
+ doevent "#001-1_163_70::OnUnTouch";
+}
+001-1,163,70,0 script #001-1_163_70 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,132,67,0 script #001-1_132_67_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-15", 34, 45;
+close;
+
+OnUnTouch:
+ doevent "#001-1_132_67::OnUnTouch";
+}
+001-1,132,67,0 script #001-1_132_67 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,101,107,0 script #001-1_101_107_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-27", 35, 34;
+close;
+
+OnUnTouch:
+ doevent "#001-1_101_107::OnUnTouch";
+}
+001-1,101,107,0 script #001-1_101_107 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,89,65,0 script #001-1_89_65_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-7", 36, 45;
+close;
+
+OnUnTouch:
+ doevent "#001-1_89_65::OnUnTouch";
+}
+001-1,89,65,0 script #001-1_89_65 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,57,41,0 warp #001-1_57_41 0,0,001-2-33,34,45
+001-1,142,30,0 script #001-1_142_30_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-12", 34, 35;
+close;
+
+OnUnTouch:
+ doevent "#001-1_142_30::OnUnTouch";
+}
+001-1,142,30,0 script #001-1_142_30 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,128,30,0 script #001-1_128_30_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-1", 37, 40;
+close;
+
+OnUnTouch:
+ doevent "#001-1_128_30::OnUnTouch";
+}
+001-1,128,30,0 script #001-1_128_30 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,104,32,0 script #001-1_104_32_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-19", 41, 30;
+close;
+
+OnUnTouch:
+ doevent "#001-1_104_32::OnUnTouch";
+}
+001-1,104,32,0 script #001-1_104_32 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,107,49,0 script #001-1_107_49_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-20", 33, 34;
+close;
+
+OnUnTouch:
+ doevent "#001-1_107_49::OnUnTouch";
+}
+001-1,107,49,0 script #001-1_107_49 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,148,54,0 script #001-1_148_54_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-11", 46, 45;
+close;
+
+OnUnTouch:
+ doevent "#001-1_148_54::OnUnTouch";
+}
+001-1,148,54,0 script #001-1_148_54 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,135,49,0 script #001-1_135_49_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-10", 51, 44;
+close;
+
+OnUnTouch:
+ doevent "#001-1_135_49::OnUnTouch";
+}
+001-1,135,49,0 script #001-1_135_49 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,118,49,0 script #001-1_118_49_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-10", 27, 44;
+close;
+
+OnUnTouch:
+ doevent "#001-1_118_49::OnUnTouch";
+}
+001-1,118,49,0 script #001-1_118_49 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,49,96,0 script #001-1_49_96_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-31", 32, 39;
+close;
+
+OnUnTouch:
+ doevent "#001-1_49_96::OnUnTouch";
+}
+001-1,49,96,0 script #001-1_49_96 NPC_ARTIS_DOOR,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-1,198,61,0 warp #001-1_198_61 0,0,001-3-0,198,59
diff --git a/npc/001-1/apana.txt b/npc/001-1/apana.txt
new file mode 100644
index 000000000..812ddfbea
--- /dev/null
+++ b/npc/001-1/apana.txt
@@ -0,0 +1,76 @@
+// Evol scripts.
+// Authors:
+// Saulc
+// Description:
+// NPC test fork from moon
+// Variables:
+// ArtisQuests_Apana - quest var
+// Quest stages:
+// 0 - not started
+// 1 - started, searching for Bug Leg
+// 2 - quest finished
+
+001-1,86,110,0 script apana NPC_PLAYER,{
+
+ .BaitID = BugLeg;
+ .BaitCount = 12;
+
+ .@q = getq(ArtisQuests_Apana);
+ if (.@q == 1) goto L_CheckItems;
+ if (.@q == 2) goto L_QuestDone;
+
+ speech S_LAST_BLANK_LINE,
+ l("I made a figurin with Bug legs."),
+ lg("Be a friend and bring me @@ @@.", "Be a friend and bring me @@ @@.", .BaitCount, getitemlink(.BaitID));
+
+ switch (select(l("I'll be back in no time."),
+ l("Sorry, I'm doing other things at the moment.")))
+ {
+ case 1:
+ setq ArtisQuests_Apana, 1;
+ speech S_FIRST_BLANK_LINE,
+ l("Thank you. I'll wait here.");
+ close;
+ case 2:
+ speech S_FIRST_BLANK_LINE,
+ l("But I'm almost out of @@...", getitemlink(.BaitID));
+ close;
+ }
+
+L_CheckItems:
+ if (countitem(.BaitID) < .BaitCount)
+ {
+ speech
+ l("Sorry, but you don't have what I need."),
+ l("I need @@ @@.", .BaitCount, getitemlink(.BaitID));
+ close;
+ }
+
+ speech
+ l("That's exactly what I needed!"),
+ l("To thank you, accept my old fishing rod."),
+ l("It's not as good as my new one, but still very useful."),
+ l("Just look at that water! There's a whole bunch of fish down there."),
+ l("Oh, and you will need this book too, it will help you learn the basics of fishing."),
+ lg("You might even get lucky, and get a @@.",
+ "You might even get lucky, and get a @@.", getitemlink(GrassCarp)),
+ l("Have a good time fishing!");
+
+ delitem .BaitID, .BaitCount;
+ Zeny = Zeny + 1000;
+ message strcharinfo(0), l("You receive @@ E!", 1000);
+ setq ArtisQuests_Apana, 2;
+ close;
+
+L_QuestDone:
+ // Idea for future: Eugene telling fishman jokes.
+ speech
+ l("Ahoy, @@!", strcharinfo(0)),
+ l("Are the fish biting today?");
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+} \ No newline at end of file
diff --git a/npc/001-1/artaxe.txt b/npc/001-1/artaxe.txt
new file mode 100644
index 000000000..9f8e02f25
--- /dev/null
+++ b/npc/001-1/artaxe.txt
@@ -0,0 +1,19 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Legion NPC blocking the north road of Artis.
+
+001-1,90,31,0 script Artaxe NPC_ARTAXE,{
+ speech S_LAST_NEXT,
+ l("Sorry buddy, you can't pass by this way, we're moving some furniture."),
+ l("Come back later!");
+
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-1/beuss.txt b/npc/001-1/beuss.txt
new file mode 100644
index 000000000..9040f64e8
--- /dev/null
+++ b/npc/001-1/beuss.txt
@@ -0,0 +1,28 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Angry member of the Legion of Aemil.
+
+001-1,45,48,0 script Beuss NPC_BEUSS,{
+ stopnpctimer;
+ initnpctimer;
+ .dir = 4;
+ mesn;
+ mesq l("You seem pathetically weak. What is such boneless jelly like you doing around here?");
+
+ goto L_Close;
+
+L_Close:
+ close;
+
+OnTimer10000:
+ .dir = 2;
+ stopnpctimer;
+ end;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-1/calypsan.txt b/npc/001-1/calypsan.txt
new file mode 100644
index 000000000..7f3d6a0ae
--- /dev/null
+++ b/npc/001-1/calypsan.txt
@@ -0,0 +1,105 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Dye seller, she sells and explain how works dye cards.
+// Version:
+// 2016.019 "Under Construction".
+// Variables:
+// ArtisQuests_Fexil
+// Quest states:
+// 0 -- not started
+// 1 -- Lloyd warned about the quest
+// 2 -- Fexil explain what he needs
+// 3 -- Fexil buy every fur that the pc bring to him
+
+001-1,47,126,0 script Calypsan#001-1 NPC_CALYPSAN,{
+
+ function explain_dyes {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Look at your equipment, can you guess what material it is made from?"),
+ l("Seek a colorant for that material:"),
+ l("Cotton, cashmere, leather, ..."),
+ l("Zinc-Titanium Oxide, Phthalocyanides, Cadmiums, Lazulite..."),
+ l("Colorant is not the yeying color. Some wear out from light, others look great but inflict itai-itai, and others become spotty or wash-away."),
+ l("What yoiis should know:"),
+ l("1: The type of item yoiis want to dye."),
+ l("2: What material it is made from."),
+ l("3: Which colorants can dye it."),
+ l("4: How many cards your item can contain."),
+ l("Exemple for yoiis:"),
+ l("Take an @@ and a @@, yeye obtains a @@.", getitemlink(ArtisTankTop), getitemlink(RedCottonDye), getitemlink(ArtisTankTop, RedCottonDye)),
+ l("If yoiis wants to see a different use for the cards he can yeye for Resa at the light armor shop for a description of the styling cards.");
+ }
+
+ function sell_dye {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("For what kind of tissue?");
+ .@tissue_type = select(l("Cotton"), l("Cashmere"));
+
+ closedialog;
+ switch (.@tissue_type)
+ {
+ case 1:
+ shop "Cotton#Dye001-1";
+ break;
+ case 2:
+ shop "Cashmere#Dye001-1";
+ break;
+ default:
+ debugmes "Calypsan script error, tissue_type is incorrect";
+ break;
+ }
+ close;
+ }
+
+ speech S_LAST_NEXT,
+ l("Yoiis envies a rainbow in the sky?"),
+ l("It is possible to yeye your cloth with my beautiful dyes."),
+ l("What does yoiis want today?");
+
+ .@fexil = getq(ArtisQuests_Fexil);
+
+ do
+ {
+ select
+ rif(.@fexil == 1, l("Have you seen Fexil?")),
+ menuaction(l("Trade")),
+ l("How do these dyes work?"),
+ l("I want to make my own dyes."),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ setcamnpc "Fexil#001-1";
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh yeye did, his store is just beside me!"),
+ l("Yoiis should look there.");
+ restorecam;
+
+ break;
+ case 2:
+ sell_dye;
+ close;
+
+ case 3:
+ explain_dyes;
+ break;
+ case 4:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Yoiis is not yet ready to make his own dyes."),
+ l("But in the future I might be able to help you create some of your own.");
+ break;
+ }
+ } while (@menu != 5);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-1/carmie.txt b/npc/001-1/carmie.txt
new file mode 100644
index 000000000..e87e7fe67
--- /dev/null
+++ b/npc/001-1/carmie.txt
@@ -0,0 +1,68 @@
+// Evol scripts.
+// Authors:
+// Alige
+// Reid
+// Description:
+// Carmie, walking NPC of the legion of Aemil on the center part of Artis.
+// Variables:
+// .@rand = Random number of sentences.
+
+001-1,86,66,0 script Carmie#001-1 NPC_RAIJIN_FEMALE_LEGION_ARTIS,{
+
+ legiontalk;
+
+ close;
+
+OnTimer1000:
+ domovestep;
+
+OnInit:
+ initpath "move", 89, 68,
+ "move", 89, 77,
+ "move", 84, 81,
+ "dir", LEFT, 0,
+ "wait", 2, 0,
+ "dir", DOWN, 0,
+ "wait", 1, 0,
+ "dir", RIGHT, 0,
+ "wait", 1, 0,
+ "move", 89, 85,
+ "dir", LEFT, 0,
+ "wait", 1, 0,
+ "dir", DOWN, 0,
+ "dir", RIGHT, 0,
+ "wait", 1, 0,
+ "move", 94, 81,
+ "dir", RIGHT, 0,
+ "wait", 2, 0,
+ "dir", DOWN, 0,
+ "wait", 1, 0,
+ "dir", LEFT, 0,
+ "wait", 1, 0,
+ "move", 89, 76,
+ "move", 89, 68,
+ "dir", LEFT, 0,
+ "wait", 2, 0,
+ "dir", DOWN, 0,
+ "wait", 4, 0,
+ "dir", RIGHT, 0,
+ "wait", 2, 0,
+ "move", 92, 66,
+ "dir", RIGHT, 0,
+ "wait", 2, 0,
+ "dir", DOWN, 0,
+ "wait", 1, 0,
+ "dir", LEFT, 0,
+ "wait", 1, 0,
+ "move", 86, 66,
+ "dir", LEFT, 0,
+ "wait", 2, 0,
+ "dir", DOWN, 0,
+ "wait", 1, 0,
+ "dir", RIGHT, 0,
+ "wait", 1, 0;
+
+ initialmove;
+ initnpctimer;
+ .distance = 5;
+}
diff --git a/npc/001-1/chelios.txt b/npc/001-1/chelios.txt
new file mode 100644
index 000000000..2846f8641
--- /dev/null
+++ b/npc/001-1/chelios.txt
@@ -0,0 +1,117 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Blacksmith's assistant of Artis
+// Variables:
+// ArtisQuests_Enora
+// Values:
+// 0 Default.
+// 1 BlackSmith quest delivered.
+// 2 Chelios Quest given.
+// 3 Chelios Quest done.
+// 4 BlackSmith gave the sword.
+
+001-1,95,109,0 script Chelios NPC_CHELIOS,{
+
+ function give_small_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Her sword... I'm having some trouble finishing it."),
+ l("You see, Enora asked me to do a black iron sword, unfortunately I ran out of the material needed, and..."),
+ l("Only Don and the Merchant Guild have that kind of material in stock. It's called black iron."),
+ l("It's better to deal with the Merchant Guild than the old man, Don has this ability to hammer down your enthusiasm in sparkling fury!"),
+ l("If Enora wants her sword now, I need to ask for your help.");
+
+ switch (select(l("Let's not keep her waiting."),
+ l("Not now.")))
+ {
+ case 1:
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("I'll be here, come back when you'll be ready.");
+
+ return;
+ }
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Thank you very much!"),
+ l("Talk with Lloyd the Banker in the Merchant Guild, it's a big building in the northern side of Artis, at the top of the small hill.");
+
+ setq ArtisQuests_Enora, 2;
+
+ return;
+ }
+
+ function more_info {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("It's the big building in northern Artis, at the top of a small hill."),
+ l("Take the east road that goes to the north and follow it until you are on top of the cliff."),
+ l("That part of the town is called the Gilded Hill, it's also where the Merchant Guild has its headquarters."), //rich hill
+ l("Lloyd still owes me, but beware of those money-grabbers, or they might sell your own teeth to you!");
+
+ return;
+ }
+
+ function quest_completed {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh... Awesome!"),
+ l("You were gone so I thought you let me down."),
+ l("Don gave me some black iron... after I asked him nearly ten times."),
+ l("But thank you anyway! I can refund him now!"),
+ l("Take the sword, and say hi to Enora for me!");
+
+ setq ArtisQuests_Enora, 4;
+
+ return;
+ }
+
+ function blacksmith_house{
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Behind me? It's the Blacksmith House, the most renowned throughout Aemil."),
+ l("There are two shops inside, they are independent from the Merchant Guild of Artis."),
+ l("Now that I think about it, they are the only shops that are independent in Artis..."),
+ l("...it might be because of Don... he is the master blacksmith of this place and a model to me!");
+
+ return;
+ }
+
+ speech S_LAST_NEXT, l("Can I be of any help?");
+
+ do
+ {
+ .@enora = getq(ArtisQuests_Enora);
+ select
+ rif(.@enora == 1, lg("I came to retrieve a package for Enora.")),
+ rif(.@enora == 3, l("I have your black iron.")),
+ rif(.@enora >= 2, l("Where is the Merchant Guild?")),
+ l("What is this building?"),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ give_small_quest;
+ break;
+ case 2:
+ quest_completed;
+ break;
+ case 3:
+ more_info;
+ break;
+ case 4:
+ blacksmith_house;
+ break;
+ }
+ } while (@menu != 5);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-1/cookiemaster.txt b/npc/001-1/cookiemaster.txt
new file mode 100644
index 000000000..77f95baa1
--- /dev/null
+++ b/npc/001-1/cookiemaster.txt
@@ -0,0 +1,258 @@
+// Evol scripts.
+// Authors:
+// Alige
+// Reid
+// Description:
+// Cookie NPC, beware, if you don't take your cookie, she'll keep it!
+// Variables:
+// General_Cookies
+// Values:
+// 0 Default, didn't get a cookie.
+// 1 Get a cookie.
+
+001-1,39,38,0 script Cookie Master NPC_COOKIE_MASTER,{
+ if ((countitem(517) == 0) && (getq(General_Cookies) == 1))
+ goto L_LostCookie;
+ if (getq(General_Cookies) == 1)
+ goto L_GetCookie;
+
+ mesn;
+ mesq lg("Hey! Adventurer! Are you enjoying your life on Aemil?");
+ next;
+
+ select
+ l("Well in fact...");
+
+ mes "";
+ mesn;
+ mesq l("Shht shht!");
+ next;
+ mesq l("Don't tell me more, I know what you want...");
+ next;
+ mesq l("A cookie!");
+ next;
+
+ menu
+ l("I'd love one!"), -,
+ l("No thank you, I'm fine. I'll come back later."), L_Bye;
+
+ mes "";
+ mesn;
+ mesq lg("Of course you do! Just listen carefully to these words my sweet.");
+ next;
+ mesq l("Cookies are a source of life.");
+ next;
+ mesq l("Cookies provide you strength, health and cuteness.");
+ next;
+ mesq l("Cookies are awesome, so am I.");
+
+ menu
+ l("Uhm... Your story seems..."), L_StorySeems,
+ l("Wait... That's not a proper place for a chef, what are you doing there?"), L_Presentation,
+ l("Exactly! Can I have one now?"), -;
+
+L_Check:
+ mes "";
+ mesn;
+ mesq l("Let me check my cookie list...");
+ next;
+
+// Beta3 Contributors.
+ if (strcharinfo(0) == "4144") goto L_Reward;
+ if (strcharinfo(0) == "Alige") goto L_Reward;
+ if (strcharinfo(0) == "enchilado") goto L_Reward;
+ if (strcharinfo(0) == "hal9000") goto L_Reward;
+ if (strcharinfo(0) == "Reid") goto L_Reward;
+ if (strcharinfo(0) == "Socapex") goto L_Reward;
+ if (strcharinfo(0) == "Kenny690") goto L_Reward;
+ if (strcharinfo(0) == "Nelson6e65") goto L_Reward;
+ if (strcharinfo(0) == "Steel Zenn") goto L_Reward;
+// Aurora1 Contributors.
+
+ mesq l("I'm sorry but I can't see your name anywhere.");
+ next;
+ mesq l("You see, folks around here that get my cookies have the distinction of being...");
+ next;
+
+ menu
+ l("Seriously? It's just a cookie you know... Tell me what I should do to get one."), L_BTaskExpanation,
+ l("Yes, yes I know... Too bad then. See you soon!"), L_Bye;
+
+L_StorySeems:
+ mes "";
+ mesn;
+ mesq l("What about my story?");
+ next;
+
+ menu
+ l("It's interesting and exciting at the same time!"), -,
+ l("Honestly, it's quite far-fetched according to me."), L_Kick;
+
+ mes "";
+ menu
+ l("Too bad. I'm not hungry enough for these cookies of yours. Maybe I'll come back later."), L_Bye,
+ l("How can I get one of these cookies?"), -;
+
+ mes "";
+ mesn;
+ mesq g(l("It looks like the sweet lady is curious, am I right?"),
+ l("It seems the gentleman is curious, am I right sweetie?"));
+ next;
+ mesq lg("Well, if you ever do want to join: 'Ye Merry Club Of Thee Bequeathed With Cookies'...");
+ next;
+
+L_BTaskExpanation:
+ mes "";
+ mesn;
+L_TaskExpanation:
+ mesq l("You'll first need to help my friends.");
+ next;
+ mesq l("It is them, after all, who have the ultimate decision as to those I can give my cookies to.");
+ next;
+
+ menu
+ l("So you're under the control of a dictatorship? That's... reassuring!"), L_Control,
+ l("Who are these friends?"), L_Friends;
+
+L_Friends:
+ mes "";
+ mesn;
+ mesq l("Shht shht!");
+ next;
+ mesq l("Don't say it so loudly, other people could hear us.");
+ next;
+ mesq l("My friends are... Well, you know... The creators.");
+ next;
+ mesq l("I can't give you a cookie for free. But I can give you this hint for how you may be added to my list.");
+ next;
+ mesq l("Now listen to and ponder my words...");
+ next;
+ mesq l("If you see weird things here and there, or things that just shouldn't be, or even in your minds eye, things that you would like to see...");
+ next;
+ mesq l("Simply contact them, by forum or wispers or irc. When you are helpful and kind, they respond in kind. And in time they may surely add you to my cookie list!");
+ next;
+
+ mesn "Narrator";
+ mes col(l("This Cookie Master rewards people who contribute and develop this world."), 9);
+ next;
+ mes col(lg("If you want to be rewarded, help us in making this world a better place."), 9);
+ next;
+ mes col(l("When you see something that looks more like a bug than a feature, report it on http://bugs.evolonline.org or try to contact a game contributor."), 9);
+ next;
+ mes col(l("Any contribution to the game (translations, graphics creation/edition, concepts, coding/scripting, etc...) is rewarded!"), 9);
+
+ mes "";
+ mesn;
+ mesq l("So, do you still want a cookie?");
+ next;
+
+ menu
+ l("I wish I helped your friends, because I'd really, really like a cookie."), -,
+ l("You tell me. Do I deserve a cookie?"), L_Check;
+
+ mes "";
+ mesn;
+ mesq l("Don't worry, I'm sure you will help them soon enough!");
+ next;
+
+ goto L_Bye;
+
+L_Presentation:
+ mes "";
+ mesn;
+ mesq l("For a chef? Who said I was a... Oh right, I am.");
+ next;
+ mesq l("I was sent here with a task. I can give you a perfect, wonderful, magnificent, superbly well shaped... Cookie!");
+ next;
+ mesq l("But...");
+ next;
+
+ goto L_TaskExpanation;
+
+L_Reward:
+ mesq l("Yes! @@ is written on my cookie list.", strcharinfo(0));
+ next;
+ mesq lg("That's quite surprising... You don't look very helpful.");
+ next;
+ mesq l("Anyway, here, have a cookie!");
+
+ inventoryplace DeliciousCookie, 1;
+
+ setq General_Cookies, 1;
+ getnameditem DeliciousCookie, strcharinfo(0);
+ npctalk3 l("You receive a @@!", getitemlink(DeliciousCookie));
+
+ next;
+ mesq lg("I'm sure you'll appreciate its effect, but be careful, these cookies are rare, and you'll need to help the community again before being able to receive another one.");
+ next;
+
+ goto L_Bye;
+
+L_Control:
+ mes "";
+ mesn;
+ mesq l("C'mon, don't be like that and loosen up! Don't you want to know who's behind all of this?!");
+ next;
+
+ menu
+ l("Why not, this might get interesting."), L_Friends,
+ l("Fine, tell me, who are these all important friends of yours?"), -,
+ l("No, and I gotta go, see you."), L_Kick;
+
+ mes "";
+ mesn;
+ mesq l("Don't belittle me, my work is deserving of the highest esteem.");
+ next;
+
+L_Kick:
+ closedialog;
+
+ npctalk3 l("No cookie for you!");
+ warp "001-1", 39, 41;
+
+ close;
+
+L_GetCookie:
+ mesq l("Hey, I'm not a Keebler Elvis! You won't have another one by stalking me like that!");
+ next;
+ mesq l("If you want another cookie, you know what to do!");
+ next;
+ mesq l("Now, move!");
+ next;
+
+ goto L_Bye;
+
+L_LostCookie:
+ mesq l("Hey, how was the...");
+ next;
+ mesq l("Wait a minute, where's the cookie I gave you?");
+ next;
+ mesq l("I'm talking about the cookie inside which I put all my love!");
+ next;
+ mesq l("The best, the wonderful, the most choice cookie among all others, the...");
+ next;
+ // Angry emote
+ mesq l("Grr...");
+ next;
+ mesq l("You're lucky that I'm a generous person, here's another one.");
+ next;
+ mesq l("This is the last one. If you use it again out of clumsiness, I will use your soft moist parts in the concoction of my next cookie batch.");
+ next;
+
+ inventoryplace DeliciousCookie, 1;
+ getnameditem DeliciousCookie, strcharinfo(0);
+
+ npctalk3 l("You receive a @@!", getitemlink(DeliciousCookie));
+
+L_Bye:
+ closedialog;
+
+ npctalk3 l("See you later!");
+
+ close;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-1/devis.txt b/npc/001-1/devis.txt
new file mode 100644
index 000000000..5f0d4868b
--- /dev/null
+++ b/npc/001-1/devis.txt
@@ -0,0 +1,100 @@
+// Evol scripts.
+// Authors:
+// Reid
+// Travolta
+// Description:
+// La Johanne crew member.
+
+001-1,193,109,0 script Devis#001-1 NPC_DEVIS_ARTIS,{
+
+ function say_random_greeting {
+ .@enora = getq(ArtisQuests_Enora);
+ if (.@enora == 0)
+ {
+ speech
+ l("Enora, from the Legion of Aemil, has been warned that you were aboard."),
+ l("She is waiting for you on the dock.");
+
+ return;
+ }
+
+ .@rand = rand(5);
+ if (.@rand == 0) goodbye;
+ else if (.@rand == 1)
+ {
+ speech S_LAST_NEXT,
+ l("A sunny and hot day,"),
+ l("a quiet place,"),
+ l("a ground!"),
+ l("What else do you need?");
+ }
+ else if (.@rand == 2) npctalk3 l("A-hoy matey!");
+ else if (.@rand == 3) npctalk3 l("We are glad captain Nard has let you join the crew!");
+ else if (.@rand == 4) npctalk3 l("Howdy?");
+
+ return;
+ }
+
+ function face_to_PC {
+ getmapxy(.@map$, .@cx, .@cy, 0);
+ @Devis_old_dir = .dir;
+ npc_turntoxy(.@cx, .@cy);
+
+ return;
+ }
+
+ function local_close {
+ if (@Devis_old_dir > 0)
+ {
+ .dir = @Devis_old_dir;
+ }
+ npc_resumemove;
+
+ close;
+ }
+
+ @Devis_old_dir = -1;
+
+ npc_pausemove;
+ face_to_PC;
+ say_random_greeting;
+ local_close;
+
+OnTimer1000:
+ dographmovestep;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 5;
+ initmovegraph "start_pos", 193, 109,
+ "dock_ent", 194, 109,
+ "dock_right", 192, 114, 195, 115,
+ "dock_left", 151, 103, 160, 106,
+ "dock_bot", 161, 119, 163, 127,
+ "dock_top", 184, 91, 195, 92,
+ "ship_ent", 19, 28,
+ "ship_sit", 28, 26,
+ "dock_mid", 174, 105;
+
+ setmovegraphcmd "start_pos", "dock_mid", 1, "dir 0; wait 2",
+ "dock_ent", "dock_right", 1, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5",
+ "dock_ent", "dock_mid", 2, "moveon",
+ "dock_bot", "dock_left", 1, "dir 6; wait 8",
+ "dock_bot", "dock_mid", 2, "moveon",
+ "dock_left", "dock_bot", 1, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5",
+ "dock_left", "dock_mid", 2, "moveon",
+ "dock_right", "dock_ent", 1, "warp 001-2-21 ship_ent",
+ "dock_right", "dock_mid", 2, "moveon",
+ "dock_top", "dock_mid", 1, "moveon",
+ "dock_mid", "dock_bot", 1, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5",
+ "dock_mid", "dock_right", 1, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5",
+ "dock_mid", "dock_left", 1, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5",
+ "dock_mid", "dock_top", 1, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5",
+ "dock_mid", "dock_ent", 2, "warp 001-2-21 ship_ent",
+ "ship_ent", "ship_sit", 1, "dir 4; sit; wait 14; stand; wait 1",
+ "ship_sit", "ship_ent", 1, "warp 001-1 dock_ent";
+
+ firstmove "wait 8", "start_pos";
+ initnpctimer;
+}
+
diff --git a/npc/001-1/doors.txt b/npc/001-1/doors.txt
new file mode 100644
index 000000000..31ca2b7df
--- /dev/null
+++ b/npc/001-1/doors.txt
@@ -0,0 +1,57 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Doors warp and animations in map 001-1
+//
+
+001-1,57,41,0 script #Warp20 NPC_HIDDEN,0,0,{
+OnTouch:
+ .@enora = getq(ArtisQuests_Enora);
+
+ if (.@enora < 11)
+ {
+ narrator S_LAST_NEXT,
+ l("The door to the legion building is temporarily closed.");
+ }
+ else
+ {
+ warp "001-2-33", 34, 46;
+ }
+
+ closedialog;
+ close;
+
+OnUnTouch:
+ doevent "#Door20::OnUnTouch";
+}
+
+001-1,57,41,0 script #Door20 NPC_ARTIS_DOOR,2,3,{
+ close;
+
+OnTouch:
+ .@enora = getq(ArtisQuests_Enora);
+ if (.@enora < 11)
+ {
+ setfakecells 57, 41, 1;
+ end;
+ }
+ setfakecells 57, 41, 0;
+ doorTouch;
+
+OnUnTouch:
+ .@enora = getq(ArtisQuests_Enora);
+ if (.@enora < 11)
+ {
+ end;
+ }
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
diff --git a/npc/001-1/elmo.txt b/npc/001-1/elmo.txt
new file mode 100644
index 000000000..170d397a0
--- /dev/null
+++ b/npc/001-1/elmo.txt
@@ -0,0 +1,20 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Sailor of Nard's La Johanne ship.
+
+001-1,185,107,0 script Elmo#001-1 NPC_ELMO_ARTIS,{
+ speech
+ l("Oh hey!"),
+ lg("If you feel bored or anxious, you can always ask some of the people around Artis if they need your help.");
+ l("It's better than running around in circles doing nothing.");
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
+
diff --git a/npc/001-1/enora.txt b/npc/001-1/enora.txt
new file mode 100644
index 000000000..fea6d6e7e
--- /dev/null
+++ b/npc/001-1/enora.txt
@@ -0,0 +1,455 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Newbie guide for Artis.
+// Variables:
+// ArtisQuests_Enora
+// Values:
+// 0 Default.
+// 1 BlackSmith quest delivered.
+// 2 Chelios Quest given.
+// 3 Chelios Quest done.
+// 4 BlackSmith gave the sword.
+// 5 Light Armor Shop quest delivered.
+// 6 Light Armor Shop gave the cloths.
+// 7 Market quest delivered.
+// 8 Q'Pid merchant.
+// 9 Market gave the potion.
+// 10 Hill quest delivered.
+// 11 Fluffy killed.
+
+001-1,176,113,0 script Enora#001-1 NPC_HUMAN_FEMALE_NOOB,{
+
+ function enora_don {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Don is renowned throughout the entire land of Aemil for his blacksmithing skills, and he is here, in Artis."),
+ l("It's a great honor for us, at the Legion, to hold the security of his business!"),
+ l("If you search for him you should look in the west of the city, it's the first house just after the left bridge, you can't miss it!"),
+ l("Chelios, his apprentice, practices outside, mostly.");
+
+ return;
+ }
+
+ function enora_legion {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("The Legion of Gasaron are a group of warriors who vowed to protect and serve their neighbours."),
+ l("We hold various training sessions, and also have a task board with a heap of things to do for the city and its surroundings."),
+ l("It's a good place to earn money, it can also help you to travel throughout the land!"),
+ l("Each big city hosts a Legion building, Artis' building is located in the north-west.");
+
+ return;
+ }
+
+ function enora_light_armor {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("The light armor shop is ran by Resa, she is part of the Merchant Guild of Artis."),
+ l("She is very skilled when it comes to weaving an ordinary piece of cloth into a wonderful work of art!"),
+ l("Her shop is on the west side of the city, between the Legion building and the library.");
+
+ return;
+ }
+
+ function enora_market {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("The market is located in the south-east of Artis, it is known as Merchant Guild's exhibit."),
+ l("You need to be a member of the Merchant Guild to have a chance there."),
+ l("And I bet you don't know who is in charge of monitoring the security of this place?");
+
+ switch (select(l("The Legion?"), l("I don't know.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You hit the nail on the head, it's the Legion of Gasaron!"),
+ l("Our main responsibility in the city is to protect the Merchant Guild.");
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Cat got your tongue?"),
+ l("..."),
+ l("Your brain liquified to match the level of a piou! It's the Legion of Gasaron.");
+ break;
+ }
+ return;
+ }
+
+ function enora_hill {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Go north from here until you find the dock warehouse, cross the bridge to the west side of the canal, continue north until you reach another bridge then cross it to the east side of the canal."),
+ l("You should arrive at a park with a hill nearby.");
+
+ return;
+ }
+
+ function enora_memories {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("It's so exciting to meet somebody with amnesia!"),
+ l("Can't you remember anything at all? Or do you have some memories of your past?"),
+ l("What happens when you try to think about it?"),
+ l("Does your mind go all fuzzy or does it feel like your head is going to explode??"),
+ l("Try doing that now!");
+
+ switch (select(l("Okay, but there won't be any explosions."),
+ lg("Don't get too excited about it...")))
+ {
+ case 1:
+ narrator S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You concentrate and try to summon old memories from within your mind."),
+ l("You feel numb and everything around you looks foggy, but you can recall the feeling of the cold hard wood of your raft on a stormy night."),
+ l("A headache hits you and you lose your concentration.");
+
+ speech S_LAST_NEXT,
+ l("So? You haven't exploded yet! Are you getting anything?");
+
+ select(l("Not really. All I got was a headache..."));
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("It's like your memories are locked away in your head! Cool!");
+
+ break;
+ case 2:
+ mes "";
+ break;
+ }
+
+ speech S_LAST_NEXT,
+ l("Ok, sorry. Back to our fluffies.");
+
+ return;
+ }
+
+ function enora_reward {
+ .@exp_reward = getarg(0);
+ .@zeny_reward = getarg(1);
+
+ getexp .@exp_reward, 0;
+ Zeny = Zeny + .@zeny_reward;
+
+ narrator S_LAST_NEXT,
+ l("You received @@ EXP and @@ E.", .@exp_reward, .@zeny_reward);
+
+ return;
+ }
+
+ function enora_first_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You probably don't have much business in this city as you don't remember who you are."),
+ lg("So I was going to ask if maybe you would be interested in giving me a hand with a few errands.");
+
+ switch (select(l("I guess so. What's in it for me?"),
+ l("Of course! What do you need?")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Some tasks will help you become aquainted with Artis. Trust me.");
+ break;
+ case 2:
+ mes "";
+ break;
+ }
+
+ speech S_LAST_NEXT,
+ l("I asked Don our blacksmith to prepare a black iron sword for morning, he should be done by now."),
+ l("Go meet him, and take the package to me, it's an easy task."),
+ l("You will be able to find Don's house in the west of the city, it's the first house just after the bridge on the left, you can't miss it!"),
+ l("A young apprentice called Chelios might be waiting outside, speak to him, and return the package to me.");
+ emotion E_HAPPY;
+
+ setq ArtisQuests_Enora, 1;
+
+ closedialog;
+ goodbye;
+ close;
+ }
+
+ function enora_second_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Thank you for this commission, Chelios is as good as Don when it comes to forging metal."),
+ l("By the way, did you ever talk with Don?"),
+ l("If so, I hope that he didn't give you any hard time, sometimes he can get up on the wrong side of the bed he becomes an embittered and grumpy old man..."),
+ l("Poor Chelios, I don't envy him..."),
+ l("So, everything went fine?");
+
+ switch (select(l("Chelios managed to do excellent work."),
+ l("The old man seemed to be senile.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("Fine, let's see his work...");
+ narrator S_LAST_NEXT, l("Enora is carefully inspecting the sword.");
+ speech S_LAST_NEXT,
+ l("Excellent!"),
+ l("The detail and craftsmanship that went into this sword can only be accomplished by the most practiced of blacksmiths.");
+
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("He may not have all of his wits but keep in mind one thing:"),
+ l("Don is renowned throughout the entire land for his blacksmith skills, and he is here, in Artis."),
+ l("It's a great honor for us, at the Legion, to hold the security of his business!");
+
+ break;
+ }
+
+ speech S_LAST_NEXT,
+ l("After this small overview of Artis, what do you think of our city?"),
+ l("The Legion of Gasaron is in charge of the security of the intramural part of our cities."),
+ l("The control and administration of the cities passes hands sometimes. You may find the Mana Order or the Brotherhood in charge instead of us at some point!"),
+ l("But we are quite lucky here, outside of some tipsy travelers there are no big problems around here, it's not like the capital, Esperia."),
+ l("Now that I think about it, I have another task for you. I asked Resa from the light armor shop to craft me some new clothes, she is a bit far from here, I can't go there because I need to watch the dock."),
+ l("Her shop is on the west side of the city, between the Legion building and the library.");
+
+ setq ArtisQuests_Enora, 5;
+ enora_reward(60, 100);
+
+ closedialog;
+ npctalk3 l("Thank you very much!");
+ close;
+ }
+
+ function enora_third_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Look how splendid this @@ is!", getitemlink(ArtisTankTop, CamelCottonDye)),
+ l("It's nearly as good as one from Esperia, have you ever been there?"),
+ l("Ah... Sorry, I forgot, again."),
+ l("I mean, you forgot... Well."),
+ l("If you ever find the time, pass by Esperia, it's the greatest city in all of Gasaron!"),
+ l("You can find the building of the Legion of Gasaron there, like in any other city, but Esperia is important for us as our headquarters are there.");
+
+ do
+ {
+ .@q = select(l("Do you still need help?"),
+ l("What is this \"legion\"?"));
+ switch (.@q)
+ {
+ case 1:
+ break;
+ case 2:
+ enora_legion;
+ break;
+ }
+ } while (.@q == 2);
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh yes, I have one last errand for you, Q'Pid in the market sells potions."),
+ l("It has been some days now since I asked her for a box of @@s, but she hasn't delivered anything yet.", getitemlink(PiberriesInfusion)),
+ l("Please try to figure out what went wrong with this order and bring me those potions."),
+ l("You will be able to find her in the market in the south-west of Artis.");
+
+ setq ArtisQuests_Enora, 7;
+ enora_reward(40, 125);
+
+ closedialog;
+ npctalk3 l("Thank you very much!");
+ close;
+ }
+
+ function enora_fourth_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Awesome!");
+
+ speech S_LAST_NEXT,
+ l("I have one more task for you. Trozz, another member of the Legion, sent me a letter earlier today."),
+ l("Some citizens are worried about the growing number of Fluffies on the hill of Artis."),
+ l("Children play there and can be badly hurt if they get too close to a Fluffy's nest."),
+ l("It would have been easy for me to handle it but if you do it, you can earn some respect by killing Fluffies instead of their natural predators!"),
+ l("Besides, I need to be here to watch out for thieves while La Johanne is docked."),
+ l("You look confident. I will give you my old gear as reward and acknowledgment for your time... and take these potions as well!");
+
+ set ArtisFluffyKilled, 0;
+
+ inventoryplace TrainingGladius, 3;
+ getitem TrainingGladius, 1;
+ getitem2 ArtisTankTop, 1, 1, 0, 0, 5005, 0, 0, 0;
+ getitem PiberriesInfusion, 5;
+ setq ArtisQuests_Enora, 10;
+ enora_reward(80, 175);
+
+ speech S_LAST_NEXT,
+ l("Do you know where the hill is?");
+
+ switch (select(l("Yes I do."),
+ l("Please guide me.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Perfect! I will wait for you here.");
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Follow the up-stream and cross the canal twice using the two bridges north from here."),
+ l("The hill is located on the north-east of Artis.");
+ break;
+ }
+
+ closedialog;
+ npctalk3 l("Thank you very much!");
+ close;
+ }
+
+ function enora_hill_cleaned {
+ if (getq2(ArtisQuests_Enora) < 9)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh no, you still have @@ Fluffies to kill.", 10 - getq2(ArtisQuests_Enora));
+
+ return;
+ }
+ else if (getq2(ArtisQuests_Enora) < 10)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Only one more Fluffy to kill and it's done!");
+
+ return;
+ }
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I cannot find the words to express my gratitude for your hard work."),
+ l("Keep the sword and the jacket, you deserved them!"),
+ l("You now also have access to the Legion building. Good job, you earned it."),
+ l("We hold various training sessions, and also have a task board with a heap of things to do for the city and its surroundings."),
+ l("It's a very good place if you want to make some more money.");
+ emotion E_WINK;
+
+ if (getq(ArtisQuests_Enora) == 10)
+ {
+ setq ArtisQuests_Enora, 11;
+ enora_reward(140, 500);
+ }
+
+ return;
+ }
+
+ function enora_quest_complete {
+ switch (getq(ArtisQuests_Enora))
+ {
+ case 4:
+ enora_second_quest;
+ break;
+ case 6:
+ enora_third_quest;
+ break;
+ case 9:
+ enora_fourth_quest;
+ break;
+ default:
+ break;
+ }
+
+ return;
+ }
+
+ function enora_paid_potions {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("Are you sure that these are my potions?");
+
+ if (askyesno() == ASK_YES)
+ {
+ delitem PiberriesInfusion, 5;
+ enora_fourth_quest;
+ }
+
+ return;
+ }
+
+ if (getq(ArtisQuests_Enora) == 0)
+ {
+ speech S_LAST_NEXT,
+ l("Hey! You must be @@.", strcharinfo(0)),
+ lg("Julia told me how they found you in the sea, on a raft with a logo of..."),
+ l("...I mean log! Made of log!"),
+ l("I also heard you lost all your memories? That's a shame."),
+ l("I'm sure you would have some interesting stories to tell!");
+ }
+ else
+ {
+ speech S_LAST_NEXT,
+ l("Hey @@!", strcharinfo(0)),
+ l("What brings you here today?");
+ }
+
+ do
+ {
+ .@q = getq(ArtisQuests_Enora);
+ select
+ rif(.@q == 0, l("She told me that you had some tasks for me.")),
+ rif(.@q == 4 || .@q == 6 || .@q == 9, l("I have your package.")),
+ rif(.@q == 8 && countitem(PiberriesInfusion) >= 5, l("I have your package.")),
+ rif(.@q >= 10, l("I cleaned up the hill.")),
+ rif(.@q >= 10, l("How many Fluffies did I kill on the hill?")),
+ rif(.@q >= 1, l("Who is Don?")),
+ rif(.@q >= 5, l("Where is the light armor shop?")),
+ rif(.@q >= 7, l("Where is the market?")),
+ rif(.@q >= 10, l("Where is the hill?")),
+ rif(.@q >= 1, l("What is this \"legion\"?")),
+ l("I wish I could remember something..."),
+ rif(.@q != 0, l("Nothing."));
+
+ switch (@menu)
+ {
+ case 1:
+ enora_first_quest;
+ break;
+ case 2:
+ enora_quest_complete;
+ break;
+ case 3:
+ enora_paid_potions;
+ break;
+ case 4:
+ enora_hill_cleaned;
+ break;
+ case 5:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You killed @@ Fluffies.", getq2(ArtisQuests_Enora));
+ if (getq2(ArtisQuests_Enora) > 8)
+ {
+ mesq l("If you continue there will be none left!");
+ next;
+ }
+ break;
+ case 6:
+ enora_don;
+ case 7:
+ enora_light_armor;
+ break;
+ case 8:
+ enora_market;
+ break;
+ case 9:
+ enora_hill;
+ break;
+ case 10:
+ enora_legion;
+ break;
+ case 11:
+ enora_memories;
+ break;
+ case 12:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Please come back anytime!");
+ }
+ } while (@menu != 12);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 5;
+ end;
+}
+
+001-1,0,0,0 script Mobs#001-1 NPC_HIDDEN,{
+ end;
+
+OnNPCKillEvent:
+ if (getq(ArtisQuests_Enora) == 10
+ && killedrid == Fluffy
+ && strcharinfo(PC_MAP) == "001-1"
+ && getq2(ArtisQuests_Enora) < 10)
+ {
+ setq(ArtisQuests_Enora, 10, getq2(ArtisQuests_Enora) + 1);
+ }
+ end;
+}
diff --git a/npc/001-1/eugene.txt b/npc/001-1/eugene.txt
new file mode 100644
index 000000000..442b950d8
--- /dev/null
+++ b/npc/001-1/eugene.txt
@@ -0,0 +1,84 @@
+// Evol scripts.
+// Authors:
+// Reid
+// Travolta
+// Description:
+// Fishman NPC
+// Quest variable:
+// ArtisQuests_Fishman
+// Quest stages:
+// 0 - not started
+// 1 - Eugene asked for items
+// 2 - completed
+
+001-1,113,120,0 script Eugene NPC_EUGENE,{
+
+ .BaitID = SmallTentacles;
+ .BaitCount = 10;
+
+ narrator S_LAST_NEXT,
+ l("You see a raijin boy, sitting on the edge of the dock."),
+ l("He's holding a fishing rod, while gazing out at the sea.");
+
+ .@q = getq(ArtisQuests_Fishman);
+ if (.@q == 1) goto L_CheckItems;
+ if (.@q == 2) goto L_QuestDone;
+
+ speech S_LAST_BLANK_LINE,
+ l("Ahoi."),
+ l("Hey, check out my brand new fishing rod. I bought it just today."),
+ l("I was so excited, I wanted to try it as soon as possible."),
+ l("So in a hurry, I forgot to take enough bait for fishing."),
+ lg("Be a friend and bring me @@ @@.", "Be a friend and bring me @@ @@.", .BaitCount, getitemlink(.BaitID));
+
+ switch (select(l("I'll be back in no time."),
+ l("Sorry, I'm doing other things at the moment.")))
+ {
+ case 1:
+ setq ArtisQuests_Fishman, 1;
+ speech S_FIRST_BLANK_LINE,
+ l("Thank you. I'll wait here.");
+ close;
+ case 2:
+ speech S_FIRST_BLANK_LINE,
+ l("But I'm almost out of @@...", getitemlink(.BaitID));
+ close;
+ }
+
+L_CheckItems:
+ if (countitem(.BaitID) < .BaitCount)
+ {
+ speech
+ l("Sorry, but you don't have what I need."),
+ l("I need @@ @@.", .BaitCount, getitemlink(.BaitID));
+ close;
+ }
+
+ speech
+ l("That's exactly what I needed!"),
+ l("To thank you, accept my old fishing rod."),
+ l("It's not as good as my new one, but still very useful."),
+ l("Just look at that water! There's a whole bunch of fish down there."),
+ l("Oh, and you will need this book too, it will help you learn the basics of fishing."),
+ lg("You might even get lucky, and get a @@.",
+ "You might even get lucky, and get a @@.", getitemlink(GrassCarp)),
+ l("Have a good time fishing!");
+
+ delitem .BaitID, .BaitCount;
+ getitem FishingRod, 1;
+ getitem FishingGuideVolI, 1;
+ setq ArtisQuests_Fishman, 2;
+ close;
+
+L_QuestDone:
+ // Idea for future: Eugene telling fishman jokes.
+ speech
+ l("Ahoy, @@!", strcharinfo(0)),
+ l("Are the fish biting today?");
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-1/fexil.txt b/npc/001-1/fexil.txt
new file mode 100644
index 000000000..55d87bc4e
--- /dev/null
+++ b/npc/001-1/fexil.txt
@@ -0,0 +1,144 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Newbie merchant.
+// Variables:
+// ArtisQuests_Fexil
+// Quest states:
+// 0 -- not started
+// 1 -- Lloyd warned about the quest
+// 2 -- Fexil explain what he needs
+// 3 -- Fexil buy every fur that the pc bring to him
+
+001-1,47,134,0 script Fexil#001-1 NPC_ELVEN_MAN_TRADER,{
+
+ function fexil_quest {
+ speech S_LAST_NEXT,
+ l("You know, the life of the merchant is hard. I really hope that Artis and the Merchant Guild will help me to succeed."),
+ l("Maybe you too you could help me?"),
+ l("I want to be the first merchant of this square to sell clothes made from @@s!", getitemlink(FluffyFur)),
+ l("I will buy all of the fur that you will bring me at a good price, let's say, 15 E piece."),
+ l("Do we have a deal?");
+
+ switch (select(l("Ok."), l("I don't want to be part of this joke.")))
+ {
+ case 1:
+ setq ArtisQuests_Fexil, 3;
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Awesome! I will wait for you here.");
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh... Ok, I will be around here if you change your mind.");
+ break;
+ }
+ return;
+ }
+
+ mesn;
+ mesq lg("Greetings traveler.");
+ next;
+ mesq l("I have some clothes and other things for you at a fine price!");
+ next;
+ mesq l("What I sell comes from every corner of Gasaron.");
+ next;
+ mesq lg("Interested?");
+ next;
+
+ if (getq(ArtisQuests_Fexil) == 1)
+ {
+ select(l("I have your pass from the Merchant Guild."));
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh! You saved me, I was too afraid to unpack my stuff without this pass."),
+ l("Hey, I remember you, we were on the same boat, you are the castaway.");
+
+ switch (select(l("Yes I am."),
+ l("You're confusing me with someone else.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh sure I remember you."),
+ l("The travel was fine for you? It was terrible for me, I was sea-sick.");
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Ah, I didn't have much sleep, it's possible.");
+ break;
+ }
+ setq ArtisQuests_Fexil, 2;
+ fexil_quest;
+
+ closedialog;
+ goodbye;
+ close;
+ }
+
+ .@fexil = getq(ArtisQuests_Fexil);
+
+ select
+ l("OK, let's trade."),
+ rif(.@fexil == 2, l("Do you still need help?")),
+ rif(.@fexil > 2 && countitem(FluffyFur) > 0, l("I have some fur for you.")),
+ l("No. Sorry.");
+
+ switch (@menu)
+ {
+ case 1:
+ closedialog;
+ shop "Bag#001-1";
+ close;
+
+ case 2:
+ mes "";
+ fexil_quest;
+ break;
+
+ case 3:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Awesome. How many of those do you want to give me?");
+
+ do
+ {
+ input .@amount;
+ if (.@amount < 1)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Please enter a valid amount.");
+ continue;
+ }
+ if (.@amount > countitem(FluffyFur))
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You don't have enough @@s on you.", getitemlink(FluffyFur));
+ continue;
+ }
+
+ break;
+ } while (1);
+
+ .@price = 15 * .@amount;
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Deal, I offer you @@ E!", .@price);
+
+ delitem FluffyFur, .@amount;
+ Zeny = Zeny + .@price;
+
+ break;
+
+ case 4:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh... Well, I just started to trade... Thus my technique may not be the best."),
+ lg("Anyway, if you ever feel interested, just check my bag!");
+ break;
+ }
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-1/flyingpiou.txt b/npc/001-1/flyingpiou.txt
new file mode 100644
index 000000000..f6132f6b9
--- /dev/null
+++ b/npc/001-1/flyingpiou.txt
@@ -0,0 +1,161 @@
+// Evol scripts.
+// Author:
+// Travolta
+// Description:
+// Pious flying around town
+// Variables:
+// none
+
+function script ArtisFlyingPiouLogic {
+ .@tick = gettimetick(1);
+ .@LastTimeTouched = getvariableofnpc(.LastTimeTouched, strnpcinfo(3));
+ if (.@tick > .@LastTimeTouched + 300)
+ {
+ .speed = 200;
+ set getvariableofnpc(.LastPlayerTouched, strnpcinfo(3)), -1;
+ }
+ .@rnd = rand(5) - 3;
+ if (.@rnd > 0)
+ return execmovecmd("wait " + .@rnd);
+ return 0;
+}
+
+001-1,53,117,0 script #FlyingPiou1 NPC_FLYING_PIOU,{
+
+ function TryCatchPiou {
+ .@agi = readparam(bAgi);
+ @ArtisQuests_CatchPiouTries += 1;
+ getmapxy(.@map$, .@x1, .@y1, 1);
+ getmapxy(.@map$, .@x2, .@y2, 0);
+ .@distance = distance(.@x1, .@y1, .@x2, .@y2);
+ .@chance = max(ArtisQuests_CatchPiou_Difficulcy,
+ 20 + .@distance * 5 - .@agi/10 -
+ @ArtisQuests_CatchPiouTries);
+ return rand(.@chance);
+ }
+
+ .@charid = getcharid(0);
+ if (.LastPlayerTouched <= 0)
+ {
+ .LastPlayerTouched = .@charid;
+ @ArtisQuests_CatchPiouTries = 0;
+ }
+ else if (.LastPlayerTouched != .@charid)
+ {
+ message strcharinfo(0), l("Hm, it seems another player is trying to catch the piou, I shouldn't interfere.");
+ end;
+ }
+
+ .@q = getq(ArtisQuests_CatchPiou);
+ if (.@q != 1)
+ {
+ mesn "Narrator";
+ mes col(l("You scare the piou, but let it go."), 9);
+ close;
+ }
+
+ .@tick = gettimetick(1);
+ if (.@tick < .LastTimeTouched + min(4, ArtisQuests_CatchPiou_Difficulcy
+ + @ArtisQuests_CatchPiouTries / 3))
+ {
+ message strcharinfo(0), l("Dang, I scared it! More patience, @@, more patience.", strcharinfo(0));
+ .LastTimeTouched = .@tick;
+ specialeffect(33, SELF);
+ end;
+ }
+
+ .LastTimeTouched = .@tick;
+
+ .@rnd = TryCatchPiou();
+ if (!.@rnd)
+ {
+ npcstop;
+ stopnpctimer;
+ getmapxy(.@map$, .@x, .@y, 1);
+ npcwalkto .@x, .@y;
+ .@trader$ = "Salem#001-1";
+ mesn "Narrator";
+ mes col(l("You caught the piou, but it's trying to escape from you. You'd better hurry back to Salem."), 9);
+ set getvariableofnpc(.LastPiouHunter$, .@trader$), strcharinfo(0);
+ set getvariableofnpc(.PiouEscapedMessage$, .@trader$), l("Oh no, the piou escaped!");
+ set getvariableofnpc(.LastPiouHunterID, .@trader$), .@charid;
+ set getvariableofnpc(.PiouCaught, .@trader$), 1;
+ donpcevent .@trader$ + "::OnPiouFlee";
+ specialeffect(26, SELF);
+ close2;
+ disablenpc strnpcinfo(3);
+ close;
+ }
+ else
+ {
+ setarray .RandomFailureMessages$[0], l("So close!"), l("It escaped!"), l("Almost got it!"), l("Oh, the little...");
+ .@r = rand(getarraysize(.RandomFailureMessages$));
+ message strcharinfo(0), .RandomFailureMessages$[.@r];
+ .speed = max(140, 200 - 10 * (@ArtisQuests_CatchPiouTries +
+ ArtisQuests_CatchPiou_Difficulcy));
+ specialeffect(33, SELF);
+ }
+ end;
+
+OnHour00:
+ .LastTimeTouched = 0;
+ end;
+
+OnTimer1000:
+ dographmovestep;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 5;
+ .walkmask = WALK_WATER;
+ // .debug = 1;
+
+ initmovegraph "market_start", 53, 117,
+ "fountain", 79, 75, 102, 91,
+ "river_bank_1", 107, 94, 117, 102,
+ "river_bank_2", 117, 110,
+ "chelios_right", 100, 112, 113, 118,
+ "chelios_left", 80, 95, 93, 111,
+ "market_right", 74, 114, 83, 121,
+ "market_center", 50, 113, 66, 121,
+ "market_left", 36, 120, 42, 128,
+ "batiment_inside", 48, 138, 65, 106,
+ "batiment_behind", 33, 90, 41, 103,
+ "library_front", 42, 82, 63, 90,
+ "taree_yard", 69, 82,
+ "taree_behind", 61, 62, 76, 71,
+ "townhall_behind", 73, 40, 93, 55,
+ "townhall_right", 99, 55, 106, 60,
+ "inn_behind", 107, 63, 123, 76
+ ;
+
+ setmovegraphcmd "fountain", "river_bank_1", 1, "call ArtisFlyingPiouLogic",
+ "river_bank_1", "river_bank_2", 1, "call ArtisFlyingPiouLogic",
+ "river_bank_2", "chelios_right", 2, "call ArtisFlyingPiouLogic",
+ "chelios_right", "chelios_left", 1, "call ArtisFlyingPiouLogic",
+ "chelios_left", "fountain", 1, "wait 1; call ArtisFlyingPiouLogic",
+ "chelios_left", "market_right", 1, "call ArtisFlyingPiouLogic",
+ "chelios_right", "market_right", 1, "call ArtisFlyingPiouLogic",
+ "market_right", "market_center", 1, "call ArtisFlyingPiouLogic",
+ "market_center", "batiment_inside",1, "call ArtisFlyingPiouLogic",
+ "batiment_inside","library_front", 1, "call ArtisFlyingPiouLogic",
+ "library_front", "taree_yard", 1, "call ArtisFlyingPiouLogic",
+ "library_front", "taree_behind", 1, "call ArtisFlyingPiouLogic",
+ "library_front", "batiment_behind",1, "call ArtisFlyingPiouLogic",
+ "batiment_behind","market_left", 1, "wait 3; call ArtisFlyingPiouLogic",
+ "market_left", "market_center", 1, "call ArtisFlyingPiouLogic",
+ "taree_yard", "fountain", 1, "call ArtisFlyingPiouLogic",
+ "taree_behind", "townhall_behind",1, "call ArtisFlyingPiouLogic",
+ "townhall_behind","townhall_right", 1, "call ArtisFlyingPiouLogic",
+ "townhall_right", "inn_behind", 1, "call ArtisFlyingPiouLogic",
+ "inn_behind", "fountain", 1, "wait 2; call ArtisFlyingPiouLogic",
+ "inn_behind", "river_bank_1", 1, "call ArtisFlyingPiouLogic",
+ "market_start", "batiment_inside",1, "call ArtisFlyingPiouLogic"
+ ;
+
+ firstmove "speed 200", "market_start";
+ initnpctimer;
+
+ .LastPlayerTouched = -1;
+ end;
+}
diff --git a/npc/001-1/harbours.txt b/npc/001-1/harbours.txt
new file mode 100644
index 000000000..f1db3fceb
--- /dev/null
+++ b/npc/001-1/harbours.txt
@@ -0,0 +1,84 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Harbour animated tiles.
+// Animation:
+// Length: 1680
+// Values:
+// 2 Hook moving down.
+// 4 Hook moving up.
+// 6 Hook down.
+// 8 Hook up.
+
+001-1,183,85,0 script #Harbour1 NPC_HARBOUR_WHEEL_BOX,{
+ harbourClic;
+
+OnTimer1670:
+ harbourTimer;
+
+OnInit:
+ .distance = 1;
+ .alwaysVisible = true;
+ end;
+}
+
+001-1,183,89,0 script #Harbour2 NPC_HARBOUR_WHEEL,{
+ harbourClic;
+
+OnTimer1670:
+ harbourTimer;
+
+OnInit:
+ .distance = 1;
+ .alwaysVisible = true;
+ end;
+}
+
+001-1,198,115,0 script #Harbour3 NPC_HARBOUR_WHEEL_BOX,{
+ harbourClic;
+
+OnTimer1670:
+ harbourTimer;
+
+OnInit:
+ .distance = 1;
+ .alwaysVisible = true;
+ end;
+}
+
+001-1,175,119,0 script #Harbour4 NPC_HARBOUR_WHEEL_BOX,{
+ harbourClic;
+
+OnTimer1670:
+ harbourTimer;
+
+OnInit:
+ .distance = 1;
+ .alwaysVisible = true;
+ end;
+}
+
+001-1,198,92,0 script #Harbour5 NPC_HARBOUR_WHEEL_BOX,{
+ harbourClic;
+
+OnTimer1670:
+ harbourTimer;
+
+OnInit:
+ .distance = 1;
+ .alwaysVisible = true;
+ end;
+}
+
+001-1,151,117,0 script #Harbour6 NPC_HARBOUR_WHEEL,{
+ harbourClic;
+
+OnTimer1670:
+ harbourTimer;
+
+OnInit:
+ .distance = 1;
+ .alwaysVisible = true;
+ end;
+}
diff --git a/npc/001-1/hinnack.txt b/npc/001-1/hinnack.txt
new file mode 100644
index 000000000..5cd7b87a4
--- /dev/null
+++ b/npc/001-1/hinnack.txt
@@ -0,0 +1,76 @@
+// Evol scripts.
+// Authors:
+// Saulc
+// Description:
+// NPC test fork from moon
+// Variables:
+// ArtisQuests_Apana - quest var
+// Quest stages:
+// 0 - not started
+// 1 - started, searching for Bug Leg
+// 2 - quest finished
+
+001-1,85,110,0 script hinnack NPC_PLAYER,{
+
+ .BaitID = BugLeg;
+ .BaitCount = 12;
+
+ .@q = getq(ArtisQuests_Apana);
+ if (.@q == 1) goto L_CheckItems;
+ if (.@q == 2) goto L_QuestDone;
+
+ speech S_LAST_BLANK_LINE,
+ l("I made a figurin with Bug legs."),
+ lg("Be a friend and bring me @@ @@.", "Be a friend and bring me @@ @@.", .BaitCount, getitemlink(.BaitID));
+
+ switch (select(l("I'll be back in no time."),
+ l("Sorry, I'm doing other things at the moment.")))
+ {
+ case 1:
+ setq ArtisQuests_Apana, 1;
+ speech S_FIRST_BLANK_LINE,
+ l("Thank you. I'll wait here.");
+ close;
+ case 2:
+ speech S_FIRST_BLANK_LINE,
+ l("But I'm almost out of @@...", getitemlink(.BaitID));
+ close;
+ }
+
+L_CheckItems:
+ if (countitem(.BaitID) < .BaitCount)
+ {
+ speech
+ l("Sorry, but you don't have what I need."),
+ l("I need @@ @@.", .BaitCount, getitemlink(.BaitID));
+ close;
+ }
+
+ speech
+ l("That's exactly what I needed!"),
+ l("To thank you, accept my old fishing rod."),
+ l("It's not as good as my new one, but still very useful."),
+ l("Just look at that water! There's a whole bunch of fish down there."),
+ l("Oh, and you will need this book too, it will help you learn the basics of fishing."),
+ lg("You might even get lucky, and get a @@.",
+ "You might even get lucky, and get a @@.", getitemlink(GrassCarp)),
+ l("Have a good time fishing!");
+
+ delitem .BaitID, .BaitCount;
+ Zeny = Zeny + 1000;
+ message strcharinfo(0), l("You receive @@ E!", 1000);
+ setq ArtisQuests_Apana, 2;
+ close;
+
+L_QuestDone:
+ // Idea for future: Eugene telling fishman jokes.
+ speech
+ l("Ahoy, @@!", strcharinfo(0)),
+ l("Are the fish biting today?");
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+} \ No newline at end of file
diff --git a/npc/001-1/juscare.txt b/npc/001-1/juscare.txt
new file mode 100644
index 000000000..393186fa3
--- /dev/null
+++ b/npc/001-1/juscare.txt
@@ -0,0 +1,93 @@
+// Evol scripts.
+// Authors:
+// Reid
+// Travolta
+// Description:
+// Juscare, walking NPC of the Legion of Aemil on the right part of the Agora of Artis.
+
+001-1,118,92,0 script Juscare#001-1 NPC_HUMAN_MALE_LEGION_ARTIS,{
+
+ function shouldTurn {
+ .@tree = findmovegraphlabel("inn_tree");
+ .@table = findmovegraphlabel("inter_inn_fav_table");
+ if (.movepos == .@tree || .movepos == .@table)
+ return 0;
+ return 1;
+ }
+
+ function localClose {
+ if (@Juscar_old_dir > 0)
+ .dir = @Juscar_old_dir;
+ npc_resumemove;
+ close;
+ }
+
+ npc_pausemove;
+ @Juscar_old_dir = -1;
+ if (shouldTurn())
+ {
+ getmapxy(.@map$, .@cx, .@cy, 0);
+ @Juscar_old_dir = .dir;
+ npc_turntoxy(.@cx, .@cy);
+ }
+
+ villagertalk();
+
+ localClose;
+
+OnTimer1000:
+ dographmovestep;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 4;
+ // .debug = 1;
+ initmovegraph
+ "inn_front", 112, 90, 119, 93,
+ "inn_tree", 108, 82,
+ "fountain", 87, 85, 91, 86,
+ "chelios", 93, 109,
+ "chelios_road", 89, 107,
+ "chelios", 93, 109,
+ "to_market", 76, 119,
+ "market", 60, 115, 65, 121,
+ "fishing_spot", 109, 127,
+ "river_bank", 113, 105,
+ "eugene", 112, 115,
+ "inn_door", 118, 89,
+ "inn_doorstep", 118, 88,
+ "inter_inn_doorstep", 29, 43,
+ "inter_inn_2tables", 38, 31,
+ "inter_inn_fav_table", 51, 33;
+
+ // this is not very obvious stuff
+ setmovegraphcmd
+ "inn_front", "inn_door", 1, 0x1, "flags_0 2; dir 4; call open_door #001-1_118_88",
+ "inn_front", "inn_tree", 2, "dir 2; wait 1; sit; wait 1; emote 106; wait 20; stand; wait 1",
+ "inn_front", "river_bank",1, "flags_0 8; flags_1 4",
+ "river_bank", "eugene", 1, 0x4, "moveon",
+ "eugene", "fishing_spot", 1, 0x4, "wait 7",
+ "fishing_spot", "chelios", 1, 0x4, "dir 6; wait 1; emote 103; wait 10",
+ "inn_tree", "inn_door", 1, "flags_1 1; flags_0 2; dir 4; call open_door #001-1_118_88",
+ "inn_tree", "fountain", 2, "dir 4; wait 1; emote 122; wait 10; dir 0; wait 1",
+ "fountain", "chelios_road", "moveon",
+ "chelios_road", "chelios", "dir 6; wait 1; emote 103; wait 7",
+ "chelios", "eugene", "flags_1 28; flags_0 4",
+ "chelios", "to_market", 2, 0x20, "flags_1 20; flags_0 10",
+ "to_market", "market", 1, 0x20, "flags_1 10; flags_0 20; wait 20",
+ "market", "to_market", "moveon",
+ "to_market", "chelios", 1, 0x10, "flags_0 10; dir 6; wait 3",
+ "fishing_spot", "eugene", 1, 0x8, "moveon",
+ "eugene", "river_bank",1, 0x8, "moveon",
+ "river_bank", "inn_front", 1, 0x8, "dir 0; wait 5",
+ "inn_door", "inn_doorstep",1, 0x1, "warp 001-2-28 inter_inn_doorstep; call close_door #001-1_118_88",
+ "inter_inn_doorstep", "inter_inn_2tables", 1, 0x1, "moveon",
+ "inter_inn_2tables", "inter_inn_fav_table", 1, 0x1, "flags_1 2; flags_0 1; dir 6; wait 1; sit; wait 15; stand; wait 1",
+ "inter_inn_fav_table", "inter_inn_2tables", 1, 0x2, "moveon",
+ "inter_inn_2tables", "inter_inn_doorstep", 1, 0x2, "call open_door #001-1_118_88; warp 001-1 inn_doorstep",
+ "inn_doorstep", "inn_door", 1, 0x2, "call close_door #001-1_118_88",
+ "inn_door", "inn_front", 1, 0x2, "flags_1 1; flags_0 2; wait 10";
+
+ firstmove "wait 4", "inn_front";
+ initnpctimer;
+}
diff --git a/npc/001-1/karim.txt b/npc/001-1/karim.txt
new file mode 100644
index 000000000..f20c1bad5
--- /dev/null
+++ b/npc/001-1/karim.txt
@@ -0,0 +1,117 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Blacksmith's assistant of Artis
+// Variables:
+// ArtisQuests_Enora
+// Values:
+// 0 Default.
+// 1 BlackSmith quest delivered.
+// 2 Chelios Quest given.
+// 3 Chelios Quest done.
+// 4 BlackSmith gave the sword.
+
+001-1,87,114,0 script karim NPC_PLAYER,{
+
+ function give_small_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Her sword... I'm having some trouble finishing it."),
+ l("You see, Enora asked me to do a black iron sword, unfortunately I ran out of the material needed, and..."),
+ l("Only Don and the Merchant Guild have that kind of material in stock. It's called black iron."),
+ l("It's better to deal with the Merchant Guild than the old man, Don has this ability to hammer down your enthusiasm in sparkling fury!"),
+ l("If Enora wants her sword now, I need to ask for your help.");
+
+ switch (select(l("Let's not keep her waiting."),
+ l("Not now.")))
+ {
+ case 1:
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("I'll be here, come back when you'll be ready.");
+
+ return;
+ }
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Thank you very much!"),
+ l("Talk with Lloyd the Banker in the Merchant Guild, it's a big building in the northern side of Artis, at the top of the small hill.");
+
+ setq ArtisQuests_Enora, 2;
+
+ return;
+ }
+
+ function more_info {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("It's the big building in northern Artis, at the top of a small hill."),
+ l("Take the east road that goes to the north and follow it until you are on top of the cliff."),
+ l("That part of the town is called the Gilded Hill, it's also where the Merchant Guild has its headquarters."), //rich hill
+ l("Lloyd still owes me, but beware of those money-grabbers, or they might sell your own teeth to you!");
+
+ return;
+ }
+
+ function quest_completed {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh... Awesome!"),
+ l("You were gone so I thought you let me down."),
+ l("Don gave me some black iron... after I asked him nearly ten times."),
+ l("But thank you anyway! I can refund him now!"),
+ l("Take the sword, and say hi to Enora for me!");
+
+ setq ArtisQuests_Enora, 4;
+
+ return;
+ }
+
+ function blacksmith_house{
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Behind me? It's the Blacksmith House, the most renowned throughout Aemil."),
+ l("There are two shops inside, they are independent from the Merchant Guild of Artis."),
+ l("Now that I think about it, they are the only shops that are independent in Artis..."),
+ l("...it might be because of Don... he is the master blacksmith of this place and a model to me!");
+
+ return;
+ }
+
+ speech S_LAST_NEXT, l("Can I be of any help?");
+
+ do
+ {
+ .@enora = getq(ArtisQuests_Enora);
+ select
+ rif(.@enora == 1, lg("I came to retrieve a package for Enora.")),
+ rif(.@enora == 3, l("I have your black iron.")),
+ rif(.@enora >= 2, l("Where is the Merchant Guild?")),
+ l("What is this building?"),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ give_small_quest;
+ break;
+ case 2:
+ quest_completed;
+ break;
+ case 3:
+ more_info;
+ break;
+ case 4:
+ blacksmith_house;
+ break;
+ }
+ } while (@menu != 5);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-1/katja.txt b/npc/001-1/katja.txt
new file mode 100644
index 000000000..2d79a7306
--- /dev/null
+++ b/npc/001-1/katja.txt
@@ -0,0 +1,129 @@
+// Evol scripts.
+// Authors:
+// Reid
+// Travolta
+// Description:
+// Little girl playing around the hill on top of the port.
+// She wants you to find her brother.
+// Variables:
+// AtrilQuests_LazyBrother = 19 -- quest var
+// LazyBrother_TreesLeft = 15 -- how many trees left to search
+// LazyBrother_TreeSearched[15] -- whether given tree was searched
+// LazyBrother_TreeWithBrother -- the number of tree where he's hiding
+// Quest states:
+// 0 - quest not started
+// 1 - Katja asked help, searching the trees
+// 2 - Bobo is found, "bad" ending
+// 3 - player decided to tell Katja where her brother is
+// 4 - "good" ending, player helped Katja
+
+001-1,164,44,0 script Katja#001-1 NPC_RAIJIN_GIRL,{
+
+ function QuestReminder {
+ setcam 5920, 960;
+ mesq l("Remember, you have to find my brother on the hill east of here.");
+ next;
+ mesq l("He is probably hiding up one of the trees. Go close to each tree and look up, otherwise you won't notice him.");
+ next;
+ restorecam;
+ }
+
+ .@q = getq(ArtisQuests_LazyBrother);
+ mesn;
+ mesq l("Hey");
+ next;
+ switch(.@q)
+ {
+ case 0:
+ mesq l("You look nice, do you want to help me?");
+ break;
+ case 1:
+ mesq l("Hi, how is it going?");
+ next;
+ select l("Remind me, what should I do?");
+ mes "";
+ mesn;
+ QuestReminder;
+ close;
+ case 2:
+ mesq l("I still didn't find my brother...");
+ close;
+ case 3:
+ mesq l("Did you find my brother?");
+ next;
+ select(l("Yes, and he promised to be home soon."));
+ mes "";
+ mesn;
+ mesq l("Oh thank you so much!");
+ next;
+ mesq l("Please take this @@ for your help.", getitemlink(Aquada)); // Need a different reward.
+ setq ArtisQuests_LazyBrother, 4;
+ getitem Aquada, 1;
+ getexp 500, 0;
+ close;
+ case 4:
+ mesq l("Thank you again for your help!");
+ close;
+ }
+ next;
+
+ switch (select(l("Of course!"),
+ l("What kind of help do you need?"),
+ l("I don't have much time right now.")))
+ {
+ case 1:
+ mes "";
+ mesn;
+ mesq l("Great!");
+ emotion E_JOY;
+ next;
+ break;
+ case 2:
+ mes "";
+ mesn;
+ break;
+ case 3:
+ mes "";
+ mesn;
+ mesq l("Okay, I'll be here, if you change your mind.");
+ emotion E_SAD;
+ close;
+ }
+
+L_Story:
+ mesq l("Mommy sent me to find my brother Bobo.");
+ next;
+ mesq l("He said he is going to climb the highest hill in Artis, which is not far from here.");
+ next;
+ mesq l("Our mommy doesn't allow us to go there, because it's dangerous. But he doesn't listen!");
+ next;
+ mesq l("Can you please go there and find him? He is probably hiding in one of those trees, like always.");
+ next;
+ mesq l("Because of the dense foliage, you need to go up close to the trees so you don't miss him.");
+ next;
+
+ switch (select(l("I will find him, don't worry!"),
+ l("Highest hill in Artis you say? Sounds dangerous, I might fall off.")))
+ {
+ case 1:
+ mes "";
+ mesn;
+ mesq l("Thank you!");
+ mes "";
+ QuestReminder;
+ setq ArtisQuests_LazyBrother, 1;
+ LazyBrother_TreesLeft = 15;
+ close;
+ case 2:
+ mes "";
+ mesn;
+ mesq l("Aw, what will I do now?");
+ close;
+ }
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 4;
+ end;
+}
+
diff --git a/npc/001-1/lucas.txt b/npc/001-1/lucas.txt
new file mode 100644
index 000000000..4058d72e3
--- /dev/null
+++ b/npc/001-1/lucas.txt
@@ -0,0 +1,19 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Legion member.
+
+001-1,59,44,0 script Lucas#001-1 NPC_LUCAS,{
+
+ villagertalk();
+
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-1/manhole.txt b/npc/001-1/manhole.txt
new file mode 100644
index 000000000..f2bae5f09
--- /dev/null
+++ b/npc/001-1/manhole.txt
@@ -0,0 +1,56 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// A manhole near Mona's house.
+// Variable:
+// ArtisQuests_MonaDad
+// Quest states:
+// 0 - Quest not started
+// 1 - Mona explained that her dad was missing
+
+001-1,152,52,0 script #manhole1-001-1 NPC_NO_SPRITE,{
+
+ if (getq(ArtisQuests_MonaDad) < 1) {
+ end;
+ }
+
+ narrator(S_LAST_BLANK_LINE | S_LAST_NEXT,
+ l("You hear some creeping and crawling sounds from the murkiness below."),
+ l("..."),
+ l("Do you want to enter in sewer?"));
+
+ if (askyesno() == 1) {
+ cwarp("001-3-0", 152, 56);
+ }
+
+ bye;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,196,35,0 script #manhole2-001-1 NPC_NO_SPRITE,{
+
+ if (getq(ArtisQuests_MonaDad) < 1) {
+ end;
+ }
+
+ narrator(S_LAST_BLANK_LINE | S_LAST_NEXT,
+ l("You hear some creeping and crawling sounds from the murkiness below."),
+ l("..."),
+ l("Do you want to enter in sewer?"));
+
+ if (askyesno() == 1) {
+ cwarp("001-3-0", 196, 36);
+ }
+
+ bye;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
diff --git a/npc/001-1/mapflags.txt b/npc/001-1/mapflags.txt
new file mode 100644
index 000000000..3e5295014
--- /dev/null
+++ b/npc/001-1/mapflags.txt
@@ -0,0 +1 @@
+001-1 mapflag town
diff --git a/npc/001-1/merlin.txt b/npc/001-1/merlin.txt
new file mode 100644
index 000000000..7a7c15906
--- /dev/null
+++ b/npc/001-1/merlin.txt
@@ -0,0 +1,25 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Fishmonger NPC
+
+001-1,73,128,0 script Merlin NPC_MERLIN,2,2,{
+
+OnTouch:
+ switch(rand(6))
+ {
+ case 0: npctalkonce(l("Fish, come and see my fish!")); break;
+ case 1: npctalkonce(l("They are fresh, they are good!")); break;
+ case 2: npctalkonce(l("Fresh from the sea and cheap!")); break;
+ case 3: npctalkonce(l("Come, come and see!")); break;
+ case 4: npctalkonce(l("They are fresh!")); break;
+ default: npctalkonce(l("Fish is good for the brain!"));
+ }
+ end;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-1/mouboo.txt b/npc/001-1/mouboo.txt
new file mode 100644
index 000000000..bee13d1e7
--- /dev/null
+++ b/npc/001-1/mouboo.txt
@@ -0,0 +1,65 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Mouboo on Taree's fence.
+
+001-1,67,79,4 script Mouboo#Artis0 NPC_MOUBOO,{
+
+ moubootalk();
+ close;
+
+OnTimer2000:
+ moubootimer;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ .speed = 600;
+ mouboograph;
+}
+
+001-1,67,80,4 script Mouboo#Artis1 NPC_MOUBOO,{
+
+ moubootalk();
+ close;
+
+OnTimer2000:
+ moubootimer;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ .speed = 600;
+ mouboograph;
+}
+
+001-1,67,81,4 script Mouboo#Artis2 NPC_MOUBOO,{
+
+ moubootalk();
+ close;
+
+OnTimer2000:
+ moubootimer;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ .speed = 600;
+ mouboograph;
+}
+
+001-1,67,82,4 script Mouboo#Artis3 NPC_MOUBOO,{
+
+ moubootalk();
+ close;
+
+OnTimer2000:
+ moubootimer;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ .speed = 600;
+ mouboograph;
+}
diff --git a/npc/001-1/nalkri.txt b/npc/001-1/nalkri.txt
new file mode 100644
index 000000000..e155a8a87
--- /dev/null
+++ b/npc/001-1/nalkri.txt
@@ -0,0 +1,59 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Nalkri, walking NPC of the Legion of Aemil on the west part of Artis.
+
+001-1,35,84,0 script Nalkri#001-1 NPC_DEMON_MALE_LEGION_ARTIS,{
+ npctalk3 l("Stay clear.");
+ close;
+
+OnTimer1000:
+ domovestep;
+
+OnInit:
+ initpath "move", 56, 84,
+ "move", 60, 93,
+ "move", 68, 98,
+ "dir", DOWN, 0,
+ "wait", 1, 0,
+ "move", 68, 100,
+ "dir", RIGHT, 0,
+ "wait", 1, 0,
+ "dir", DOWN, 0,
+ "wait", 1, 0,
+ "dir", LEFT, 0,
+ "wait", 1, 0,
+ "dir", UP, 0,
+ "move", 67, 98,
+ "dir", RIGHT, 0,
+ "wait", 2, 0,
+ "move", 51, 101,
+ "dir", LEFT, 0,
+ "wait", 1, 0,
+ "dir", DOWN, 0,
+ "wait", 1, 0,
+ "dir", RIGHT, 0,
+ "wait", 1, 0,
+ "dir", UP, 0,
+ "move", 48, 100,
+ "dir", RIGHT, 0,
+ "wait", 1, 0,
+ "dir", DOWN, 0,
+ "wait", 1, 0,
+ "dir", LEFT, 0,
+ "wait", 1, 0,
+ "dir", RIGHT, 0,
+ "move", 55, 96,
+ "move", 43, 88,
+ "move", 35, 84,
+ "dir", LEFT, 0,
+ "wait", 1, 0,
+ "dir", DOWN, 0,
+ "wait", 4, 0,
+ "dir", RIGHT, 0,
+ "wait", 1, 0;
+
+ initialmove;
+ initnpctimer;
+}
diff --git a/npc/001-1/panels.txt b/npc/001-1/panels.txt
new file mode 100644
index 000000000..a82fbabd1
--- /dev/null
+++ b/npc/001-1/panels.txt
@@ -0,0 +1,57 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Panels to give advice and some random information to players.
+
+001-1,180,25,0 script #ArtisPanel1 NPC_NO_SPRITE,{
+ narrator S_LAST_NEXT,
+ l("You step on something, a panel half overgrown by moss, it has writing on it...");
+
+ mesq l("Don't fall!");
+ next;
+ mesq l("You've reached the highest natural place of Artis, enjoy the view.");
+ next;
+
+ closedialog;
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
+
+001-1,95,51,0 script #ArtisPanel2 NPC_NO_SPRITE,{
+ narrator S_LAST_NEXT,
+ l("You step on something, a shaky and fragile panel with barely visible inscriptions on it...");
+
+ mesq l("Beware of falling stones from the cliff!");
+ next;
+ mesq l("The other part of this sign has been crushed by a rock.");
+ next;
+
+ closedialog;
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
+
+001-1,103,66,0 script #ArtisPanel3 NPC_NO_SPRITE,{
+ narrator S_LAST_NEXT,
+ l("You step on something, a panel with a bitten corner and clear inscriptions on it...");
+
+ mesq l("Warning! Dangerous fish, do not fall into the lake!");
+ next;
+ narrator S_LAST_NEXT,
+ l("Somebody tried to stroke the word \"fish\" and tried to replace it with \"sharkes\".");
+
+ closedialog;
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
+
diff --git a/npc/001-1/pious.txt b/npc/001-1/pious.txt
new file mode 100644
index 000000000..10f9d8e45
--- /dev/null
+++ b/npc/001-1/pious.txt
@@ -0,0 +1,16 @@
+// Evol scripts.
+// Author:
+// Travolta
+// Description:
+// Pious on Market
+// Variables:
+// none
+
+001-1,55,119,0 script #MarketPiou1 NPC_MARKET_PIOU,{
+ end;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-1/qonan.txt b/npc/001-1/qonan.txt
new file mode 100644
index 000000000..fe255799f
--- /dev/null
+++ b/npc/001-1/qonan.txt
@@ -0,0 +1,111 @@
+// Evol scripts.
+// Authors:
+// Reid
+// Travolta
+// Description:
+// Sailor of Nard's La Johanne ship.
+// ArtisQuests_QOnan -- quest variable:
+// 0 - not started
+// 1 - Q'Onan asked to find Chest
+// 2 - Chest found, heading back to Q'Onan
+// 3 - Quest completed
+
+001-1,186,107,0 script Q'Onan#001-1 NPC_QONAN,{
+
+ .@q = getq(ArtisQuests_QOnan);
+ if (.@q == 1) goto L_QuestGiven;
+ if (.@q == 2) goto L_ItemFound;
+ if (.@q == 3) goto L_QuestDone;
+
+ speech S_LAST_BLANK_LINE,
+ l("We haven't met, right?"),
+ l("My name is Q'Onan, I'm a member of Nard's crew."),
+ l("I have a lot of work here, so I don't even have time to go to the town."),
+ l("Could you do a small favor for me?");
+
+ switch (select(l("Go on."), l("I don't have the time sorry.")))
+ {
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("No problem, see you next time.");
+ closedialog;
+ close;
+ }
+
+ speech S_FIRST_BLANK_LINE | S_LAST_BLANK_LINE,
+ l("Before I joined Nard, I used to be a thief."),
+ l("I'm not proud of it, but I had to steal money from others to keep on living."),
+ l("Anyway, the last time I stole something I was almost caught."),
+ l("I robbed a nobleman, took a chest full of coins."),
+ l("But my luck left me, because as soon as I left his house, the guards started chasing me."),
+ l("It was at night, so I could barely escape. I ran to Artis hill."),
+ l("I was afraid to get busted, so I decided to get rid of the evidence."),
+ l("I buried the chest somewhere on that hill. It was dark, so I don't remember where to dig exactly."),
+ l("I'm afraid to go there myself, but if you take the risk, you can have half of the loot."),
+ l("So, what do you say?");
+
+ select
+ l("I like money! Consider it done."),
+ l("Too risky, I might end up in jail. Do it yourself.");
+
+ switch(@menu)
+ {
+ case 1:
+ setq ArtisQuests_QOnan, 1;
+ getrandompoint(178,26,182,29);
+ npcdebug "Chest buriad at (" + .move__rand_x + "," + .move__rand_y + ")";
+ shovel_addquest("001-1", .move__rand_x, .move__rand_y, "QOnanFoundItem");
+ speech S_FIRST_BLANK_LINE | S_LAST_BLANK_LINE,
+ l("Alright, you will need this shovel."),
+ l("You should check on the highest part of the cliff, I was hiding there."),
+ l("I hope to see you soon.");
+ getitem IronShovel, 1;
+ close;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_BLANK_LINE,
+ l("Come on, don't be a coward!"),
+ l("Anyway, let me know if you change your mind.");
+ close;
+ }
+
+L_QuestGiven:
+ speech S_LAST_NEXT, lg("I asked you to do me a favor, did you forget?");
+ select l("What should I do, again?");
+ speech S_FIRST_BLANK_LINE,
+ l("Please find the small chest, buried somewhere on Artis hill."),
+ l("You should check on the highest part of the cliff, I was hiding there."),
+ l("Bring it to me, and you will get your reward.");
+ close;
+
+L_ItemFound:
+ speech
+ l("After all this time, it was still there!"),
+ lg("We are very lucky, my friend."),
+ l("Let me open it with my key."),
+ l("Like I promised, here is your share."),
+ l("I can finally pay off my debts.");
+
+ Zeny += 1800;
+ setq ArtisQuests_QOnan, 3;
+ close;
+
+L_QuestDone:
+ speech l("Howdy, partner in crime?");
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ .debug = 1;
+ end;
+}
+
+function script QOnanFoundItem {
+ setq ArtisQuests_QOnan, 2;
+ // getitem SmallChest, 1;
+ narrator S_FIRST_BLANK_LINE,
+ l("You found a small chest, surprisingly heavy for it's size."),
+ l("It's probably full of coins, but no matter how hard you try to open it, you can't."),
+ l("Better take it back to Q'Onan.");
+ return;
+}
diff --git a/npc/001-1/qpid.txt b/npc/001-1/qpid.txt
new file mode 100644
index 000000000..d4194ddd5
--- /dev/null
+++ b/npc/001-1/qpid.txt
@@ -0,0 +1,170 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Potion seller, she is part of the Enora's noob quests.
+
+001-1,65,116,0 script Q'Pid#001-1 NPC_QPID,{
+
+ function riddle_enigma {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Ok fine, you have up to 3 tries, here is the riddle:"),
+ l("What is growing and shrinking at the same time?");
+ narrator S_LAST_NEXT,
+ l("You need to type the answer of this riddle in the NPC window."),
+ l("The answer is a single word, without conjugation."),
+ l("You can also answer in your native language or in English.");
+
+ do
+ {
+ input .@answer$;
+ .@i++;
+
+ if (riddlevalidation(.@answer$, "life", l("life")))
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh..."),
+ l("You seem more cultivated than you look.");
+
+ if (getq(ArtisQuests_Enora) == 7)
+ {
+ setq(ArtisQuests_Enora, 9);
+ speech S_LAST_NEXT | S_NO_NPC_NAME,
+ l("Fine, take these potions, I will replenish them in the next couple hours anyway.");
+ }
+
+ break;
+ }
+ else if (.@i < 3)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Too bad, try again.");
+ }
+ else
+ {
+ if (getq(ArtisQuests_Enora) == 7)
+ {
+ setq(ArtisQuests_Enora, 8);
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You failed!"),
+ l("Ivan is the one you should look for now."),
+ l("He is in a small house between the dock's warehouse and the dojo."),
+ l("Follow the canal to the north-east and you will find it."),
+ l("And get out of here, I'm not a map!");
+ }
+ else
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You failed!");
+ }
+
+ break;
+ }
+ } while (true);
+
+ return;
+ }
+
+ function enora_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("She wants? What if I don't want?"),
+ l("I'm not a pawn of the Legion, I don't have to obey you!"),
+ l("Oh and guess what! I'm almost out of potions anyway.");
+
+ switch (select(l("And where can I find these potions?"),
+ l("You bored me, see you later.")))
+ {
+ case 1:
+ break;
+ case 2:
+ return;
+ }
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You don't seem to be from the Legion, let's do a game."),
+ l("If you find the correct answer, I will give you these potions..."),
+ l("But if you fail, you will have to get them from the alchemist."),
+ l("Deal?");
+
+ if (askyesno() == ASK_YES)
+ {
+ riddle_enigma;
+ }
+ return;
+ }
+
+ function alchemist_information {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Do? I don't do them."),
+ l("I'm sure that you already knew the answer, didn't you?"),
+ l("You tried to embarrass me, am I right?!"),
+ lg("It's Ivan... I'm sure that he sent you to annoy me..."),
+ l("I'm just a merchant, I trade and make deals, yes \"excuse\" me if I'm not as skilled as that stupid alchemist."),
+ l("But rare are those that receive grants from the Legion itself. For anybody else only a hard work can pay your bills!");
+ emotion E_UPSET;
+
+ switch (select(l("Sorry I didn't mean to bother you."),
+ l("You are just sitting on the shadow of your store.")))
+ {
+ case 1:
+ mes "";
+ mesn;
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("You are honest, I like it.");
+ break;
+ }
+ mesq l("Is that all you had to say?");
+ next;
+
+ return;
+ }
+
+ speech S_LAST_NEXT,
+ l("What?");
+
+ do
+ {
+ .@enora = getq(ArtisQuests_Enora);
+
+ select
+ rif(.@enora == 7, l("Enora wants her potions.")),
+ menuaction(l("Trade")),
+ rif(.@enora > 7, l("What was your riddle?")),
+ l("How do you do your potions?"),
+ l("What are you reading?"),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ enora_quest;
+ break;
+ case 2:
+ closedialog;
+ shop "Store#Potion001-1";
+ close;
+ case 3:
+ riddle_enigma;
+ break;
+ case 4:
+ alchemist_information;
+ break;
+ case 5:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("It's a poem, about poems... Why are you asking that?"),
+ l("Because I am a Kralog I can't read such things? That's rubbish."),
+ l("I borrowed it from the library, you should try to cultivate yourself more instead of insinuate things about people you don't know!");
+ break;
+ }
+ } while (@menu != 6);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 3;
+ end;
+}
diff --git a/npc/001-1/rumly.txt b/npc/001-1/rumly.txt
new file mode 100644
index 000000000..4a1103fbb
--- /dev/null
+++ b/npc/001-1/rumly.txt
@@ -0,0 +1,226 @@
+// Evol scripts.
+// Author:
+// Vasily_Makarov
+// Description:
+// Stat resetter.
+// Variables:
+// General_Rumly
+// Values:
+// 0 Player hasn't met Rumly
+// 1 Last time player has told that he will never come back
+// 2 Last time player has told that he will come back later
+// 3 Player has already reset his stat
+// Others:
+// .@visited - Rumly actual variable
+// .@wasSP - free status points before reset
+
+001-1,35,125,0 script Rumly#001-1 NPC_RUMLY,{
+
+ setnpcdir "Rumly#001-1", 2;
+ stopnpctimer;
+ initnpctimer;
+
+ speech S_LAST_NEXT,
+ l("Hey you, do you have any @@s?", getitemlink(Plushroom));
+
+L_Menu:
+ .@visited = getq(General_Rumly);
+ .@plush_count = lognbaselvl(1, 10);
+
+ select
+ l("Plushrooms you say?"),
+ l("Who are you?"),
+ rif(.@visited > 0, l("Can you reset my stats please?")),
+ lg("You are weird, I have to go sorry.");
+
+ switch (@menu)
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Wind and grass is nice and cool, so juicy sweet..."),
+ l("Our only wish to eat a plush, so juicy sweet...");
+ goto L_Menu;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("Why are you asking? And who are you too? I've never seen you around before..."),
+ lg("Wait, are you one of those from the Legion of Gasaron? I didn't do anything wrong, I promise!"),
+ l("I... I just like to eat the purple and delightful... And natural, and...");
+
+ switch (select(l("Chill out I won't say anything."),
+ l("Yes I am and you are going to face justice!")))
+ {
+ case 1: break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("No! No, no, my precious plushrooms! Don’t take me to them, they wants my precious.");
+ goto L_Quit;
+ }
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I won't forget it, I swear on my precious plushrooms!"),
+ l("There is an unknown side effect to these plushrooms, they can free you from your past mistakes."),
+ l("You can use it to clear your stats, to start freshly if you see what I mean..."),
+ l("Bring me some of these plushrooms and I will show you how it works!"),
+ l("Although the more powerful you are, the more plushrooms you will need.");
+
+ select
+ l("Sounds good!"),
+ rif(countitem(Plushroom) >= .@plush_count, lg("I think I have enough plushrooms on me.")),
+ l("We will talk about it later."),
+ l("My stats are too good, I won't need it.");
+
+ switch (@menu)
+ {
+ case 1:
+ if (.@visited < 2)
+ {
+ setq General_Rumly, 2;
+ }
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Great! Can't wait for some tasty mushrooms!");
+
+ goto L_Menu;
+ case 2:
+ goto L_ResetStats;
+ case 3:
+ goto L_Later;
+ case 4:
+ goto L_Never;
+ }
+
+ case 3:
+ goto L_ResetStats;
+ case 4:
+ if (.@visited < 2) goto L_Quit;
+
+ .@rand = rand(2);
+
+ if (.@rand)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("See you! And come back with the plushrooms!");
+ }
+ else
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh noes!"),
+ l("A rabbit!"),
+ l("He has a guns!"),
+ l("*Bang bang*");
+ narrator S_LAST_NEXT,
+ l("Rumly is hiding behind the tree.");
+ }
+
+ goto L_Quit;
+ }
+
+L_ResetStats:
+ if (.@visited == 1)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("Changed your mind, uh?"),
+ l("Very good."),
+ l("Status point reset can't be undone. Do you really want this?"),
+ lg("Are you sure about this?");
+ }
+ else
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("Are you sure about this?");
+ }
+
+L_ConfirmReset:
+ switch (select(lg("Yes, I am sure."),
+ lg("I need to think about it..."),
+ lg("I won't need it, thank you.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Let me just have a quick look at you. Hm... I will need @@ @@s to reset your stats.", .@plush_count, getitemlink(Plushroom));
+
+ select
+ rif(countitem(Plushroom) >= .@plush_count, lg("Here, take as many as you need, I have plenty!")),
+ rif(countitem(Plushroom) > 0 && countitem(Plushroom) < .@plush_count, lg("I don't have enough plushrooms...")),
+ rif(countitem(Plushroom) == 0, lg("Oh no, I don't have any plushroom on me right now.")),
+ lg("I have to go, sorry.");
+
+ if (@menu > 1)
+ {
+ goto L_Later;
+ }
+
+ delitem Plushroom, .@plush_count;
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Thank you."),
+ l("Now stand still... It should not take much time...");
+
+ .@wasSP = StatusPoint;
+ resetstatus;
+ if (.@visited < 3)
+ {
+ setq General_Rumly, 3;
+ }
+ if (StatusPoint == .@wasSP)
+ {
+ speech S_LAST_NEXT,
+ l("It seems that you have no status points to reset!"),
+ lg("But the plushroom you brought was really awesome you know."),
+ lg("Come back when you will really need me. And bring more plushrooms with you!");
+ }
+ else
+ {
+ speech S_LAST_NEXT,
+ l("Let's see... @@ of your status points have just been reset!", StatusPoint - .@wasSP),
+ l("Spend it wisely this time."),
+ lg("But you are welcome to reset your stats again if you bring me some more plushrooms!");
+ }
+ goto L_Quit;
+
+ case 2:
+ goto L_Later;
+ case 3:
+ goto L_Never;
+ }
+
+L_Later:
+ if (.@visited < 2)
+ {
+ setq General_Rumly, 2;
+ }
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Come back soon, and bring @@s!", getitemlink(Plushroom));
+
+ goto L_Quit;
+
+L_Never:
+ if (.@visited < 2)
+ {
+ setq General_Rumly, 1;
+ }
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("I am sure that you will change your mind.");
+
+ goto L_Quit;
+
+L_Quit:
+ setnpcdir "Rumly#001-1", 4;
+ stopnpctimer;
+ initnpctimer;
+
+ goodbye;
+
+OnTimer1800:
+ stopnpctimer;
+
+ if (getnpcdir("Rumly#001-1") == 2) setnpcdir "Rumly#001-1", 6;
+ if (getnpcdir("Rumly#001-1") == 4) setnpcdir "Rumly#001-1", 8;
+
+ end;
+
+OnInit:
+ .sex = G_MALE;
+ end;
+}
diff --git a/npc/001-1/salem.txt b/npc/001-1/salem.txt
new file mode 100644
index 000000000..b80cb76e4
--- /dev/null
+++ b/npc/001-1/salem.txt
@@ -0,0 +1,220 @@
+// Evol scripts.
+// Author:
+// Travolta
+// Description:
+// Trader on the market. One of his pious escaped and
+// flies around the town.
+// Variables:
+// ArtisQuests_CatchPiou -- quest variable
+// Quest states:
+// 0 -- not started
+// 1 -- trader asked to catch piou
+// 2 -- quest finished
+// Note: this script is ugly like hell
+
+001-1,57,118,0 script Salem#001-1 NPC_SALEM,{
+
+ function BuyPiou {
+ .@price = getarg(0);
+ mesq l("The piou costs @@ E.", .@price);
+ next;
+ select
+ l("Alright, I'll take one."),
+ l("I changed my mind.");
+
+ mes "";
+ mesn;
+ if (@menu == 2)
+ return 4;
+ if (Zeny < .@price)
+ {
+ mesq l("Don't you try to cheat an old merchant! You don't have enough money, you need @@ E.", .@price);
+ next;
+
+ return 1;
+ }
+ if (!checkweight(PiouEgg, 1))
+ {
+ mesq l("You can't carry another @@? What a shame.", PiouEgg);
+ next;
+
+ return 2;
+ }
+ getinventorylist;
+ if (.@inventorylist_count >= 100)
+ {
+ mesq l("You don't have enough room in your backpack for a @@. Go stow some of your junk and come back.", PiouEgg);
+ next;
+
+ return 3;
+ }
+ Zeny = Zeny - .@price;
+ getitem PiouEgg, 1;
+ ArtisQuests_PiousBought += 1;
+ mesq l("You take good care of your piou. Remember to feed it every day.");
+
+ return 0;
+ }
+
+// if (2 == select("[debug]continue quest:[debug] start over"))
+// {
+// debugmes "Starting quest CatchPiou over";
+// setq ArtisQuests_CatchPiou, 0;
+// }
+
+ .@q = getq(ArtisQuests_CatchPiou);
+ @ArtisQuests_PiouPrice = 30000;
+
+ if (.@q == 1)
+ {
+ if (.PiouCaught)
+ {
+ speech
+ l("Look who is back..."),
+ l("And with my piou. That's wonderful. I can only imagine how hard that little bugger was to catch!"),
+ l("Great, and as I promised, I give you a 90% discount on the @@ of your choice.", getitemlink(PiouEgg));
+ next;
+
+ @ArtisQuests_PiouPrice = 3000;
+ ArtisQuests_PiouDiscount = 1;
+ donpcevent strnpcinfo(3) + "::OnPiouFlee";
+ setq ArtisQuests_CatchPiou, 2;
+ .@q = getq(ArtisQuests_CatchPiou);
+
+ .LastPiouHunter$ = "";
+ ArtisQuests_CatchPiou_Difficulcy = 0;
+ .@BoughtPiou = BuyPiou(@ArtisQuests_PiouPrice);
+ if (.@BoughtPiou == 0)
+ ArtisQuests_PiouDiscount = 0;
+ else if (.@BoughtPiou == 4)
+ speech S_FIRST_BLANK_LINE, l("See you next time!");
+
+ close;
+ }
+ else
+ {
+ speech
+ l("Look who is back..."),
+ l("So, where is my piou? You should not keep an old man waiting. Go and catch it like you said you would.");
+ next;
+ goto L_SalemMenuShop;
+ }
+ }
+
+ speech S_LAST_NEXT,
+ l("Good day, my friend, come closer, come closer!");
+ l("Just look at my goods for sale! Fresh fruits and vegetables were shipped only this morning. And for reasonable price, of course.");
+
+L_SalemMenuShop:
+ .@fexil = getq(ArtisQuests_Fexil);
+
+ select
+ l("What about those pious? They look so cute."),
+ l("Let's trade."),
+ rif(.@q != 0, l("I'd like to buy a piou.")),
+ rif(.@fexil == 1, l("I'm looking for somebody named Fexil.")),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ goto L_AboutPious;
+ break;
+ case 2:
+ closedialog;
+ shop "Store#General001-1";
+ close;
+ case 3:
+ if (.@q == 2 && ArtisQuests_PiouDiscount)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You still have a 90% discount on one piou.");
+ @ArtisQuests_PiouPrice = 3000;
+ }
+ if (!BuyPiou(@ArtisQuests_PiouPrice))
+ ArtisQuests_PiouDiscount = 0;
+ break;
+ case 4:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I think that I've seen this weakling wandering around the beach south from here this morning.");
+ break;
+ }
+
+ closedialog;
+ goodbye;
+ close;
+
+L_AboutPious:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Ah, the locals like keeping them as pets.");
+ l("With proper training, a piou can become a good friend and faithful companion in your adventures.");
+
+ if (getq(ArtisQuests_CatchPiou) >= 2)
+ {
+ goto L_SalemMenuShop;
+ }
+
+ mesq l("Their price is usually high, but you know what? I have a bargain offer for you.");
+ next;
+ mesq l("These little pious here can't fly. At least that's what I thought.");
+ next;
+ mesq l("One of these little boogers started flying early, and escaped from me.");
+ next;
+ mesq l("It's still too young to fly too far away, so it just circles nearby.");
+ next;
+ mesq l("But I can't leave to catch it, so I'm asking you.");
+ next;
+ mesq l("If you catch the escaped piou and bring it back, I will give you a 90% discount on a piou.");
+ next;
+
+ select
+ rif(.@q == 0, l("Sounds like a good deal to me. I'll do it.")),
+ rif(.@q == 1, l("I'm on my way! I will bring it back to you.")),
+ l("I don't really have time to go chasing pious, let me just buy one at the regular price (30000 E)."),
+ l("I don't want to buy a piou right now.");
+
+ mes "";
+ mesn;
+
+ switch (@menu)
+ {
+ case 1:
+ goto L_QuestInfo;
+ case 3:
+ BuyPiou @ArtisQuests_PiouPrice;
+ }
+ closedialog;
+ goodbye;
+ close;
+
+L_QuestInfo:
+ mesq l("The little piou is flying nearby, all you need is to catch it and bring back to me.");
+ next;
+ setq ArtisQuests_CatchPiou, 1;
+ ArtisQuests_CatchPiou_Difficulcy = 2;
+ mesq l("Good luck!");
+ close;
+
+OnPiouFlee:
+ sleep 120000;
+ if (!.PiouCaught)
+ end;
+ .PiouCaught = 0;
+ .@piou$ = "#FlyingPiou1";
+ if (getstrlen(.LastPiouHunter$) > 0)
+ {
+ message .LastPiouHunter$, .PiouEscapedMessage$;
+ .LastPiouHunter$ = "";
+ }
+ // debugmes "The piou escaped from " + .LastPiouHunter$;
+ sleep 60000;
+ enablenpc .@piou$;
+ movenpc .@piou$, 53, 117;
+ donpcevent .@piou$ + "::OnInit";
+ end;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 5;
+ end;
+}
diff --git a/npc/001-1/shop.txt b/npc/001-1/shop.txt
new file mode 100644
index 000000000..e3894b8d3
--- /dev/null
+++ b/npc/001-1/shop.txt
@@ -0,0 +1,318 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Market shops.
+
+001-1,46,135,0 trader Bag#001-1 NPC_SHOP_BAG,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem PiouLegs, -1, 15;
+ sellitem Bread, -1, 15;
+ sellitem Croconut, -1, 50;
+ sellitem Aquada, -1, 50;
+ sellitem Armbands, -1, 20;
+ sellitem LousyMoccasins, -1, 20;
+ sellitem PiouSlayer, -1, 15;
+
+ .sex = G_OTHER;
+ .distance = 3;
+ end;
+
+OnClock0000:
+ restoreshopitem PiouLegs, 15;
+ restoreshopitem Bread, 15;
+ restoreshopitem Croconut, 50;
+ restoreshopitem Aquada, 50;
+ restoreshopitem Armbands, 20;
+ restoreshopitem LousyMoccasins, 20;
+ restoreshopitem PiouSlayer, 15;
+}
+
+001-1,49,136,0 trader Warrior Shop#001-1-1 NPC_SHOP_BAG,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem WarlordHelmet, -1, 15;
+ sellitem WarlordPlate, -1, 15;
+ sellitem GoldenRubyRing, -1, 50;
+ sellitem RawTalisman, -1, 50;
+ sellitem OldTowel, -1, 20;
+ sellitem TerranitePants, -1, 20;
+ sellitem TerraniteArmor, -1, 15;
+ sellitem GoldenDiamondRing, -1, 15;
+ sellitem Ruby, -1, 15;
+ sellitem BromenalShield, -1, 15;
+
+ .sex = G_OTHER;
+ .distance = 3;
+ end;
+
+OnClock0000:
+ restoreshopitem PiouLegs, 15;
+ restoreshopitem Bread, 15;
+ restoreshopitem Croconut, 50;
+ restoreshopitem Aquada, 50;
+ restoreshopitem Armbands, 20;
+ restoreshopitem LousyMoccasins, 20;
+ restoreshopitem PiouSlayer, 15;
+}
+
+001-1,46,125,0 trader Cotton#Dye001-1 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem BlackCottonDye, -1, 10;
+ sellitem SilverCottonDye, -1, 10;
+ sellitem CamelCottonDye, -1, 10;
+ sellitem BrownCottonDye, -1, 10;
+ sellitem OrangeCottonDye, -1, 10;
+ sellitem DarkRedCottonDye, -1, 10;
+ sellitem RedCottonDye, -1, 10;
+ sellitem FuschiaCottonDye, -1, 10;
+ sellitem PinkCottonDye, -1, 10;
+ sellitem MauveCottonDye, -1, 10;
+ sellitem PurpleCottonDye, -1, 10;
+ sellitem NavyBlueCottonDye, -1, 10;
+ sellitem BlueGrayCottonDye, -1, 10;
+ sellitem BlueCottonDye, -1, 10;
+ sellitem TealCottonDye, -1, 10;
+ sellitem GreenCottonDye, -1, 10;
+ sellitem LimeCottonDye, -1, 10;
+ sellitem KhakiCottonDye, -1, 10;
+ sellitem YellowCottonDye, -1, 10;
+
+ .sex = G_OTHER;
+ .distance = 4;
+ end;
+
+OnClock0000:
+ restoreshopitem BlackCottonDye, 10;
+ restoreshopitem SilverCottonDye, 10;
+ restoreshopitem CamelCottonDye, 10;
+ restoreshopitem BrownCottonDye, 10;
+ restoreshopitem OrangeCottonDye, 10;
+ restoreshopitem DarkRedCottonDye, 10;
+ restoreshopitem RedCottonDye, 10;
+ restoreshopitem FuschiaCottonDye, 10;
+ restoreshopitem PinkCottonDye, 10;
+ restoreshopitem MauveCottonDye, 10;
+ restoreshopitem PurpleCottonDye, 10;
+ restoreshopitem NavyBlueCottonDye, 10;
+ restoreshopitem BlueGrayCottonDye, 10;
+ restoreshopitem BlueCottonDye, 10;
+ restoreshopitem TealCottonDye, 10;
+ restoreshopitem GreenCottonDye, 10;
+ restoreshopitem LimeCottonDye, 10;
+ restoreshopitem KhakiCottonDye, 10;
+ restoreshopitem YellowCottonDye, 10;
+}
+
+001-1,48,125,0 trader Cashmere#Dye001-1 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem CrimsonCashmereDye, -1, 7;
+ sellitem ChocolateCashmereDye, -1, 7;
+ sellitem MintCashmereDye, -1, 7;
+
+ .sex = G_OTHER;
+ .distance = 4;
+ end;
+
+OnClock0000:
+ restoreshopitem CrimsonCashmereDye, 7;
+ restoreshopitem ChocolateCashmereDye, 7;
+ restoreshopitem MintCashmereDye, 7;
+}
+
+001-1,64,114,0 trader Store#Aquada001-1 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem Aquada, -1, 50;
+
+ .sex = G_OTHER;
+ .distance = 4;
+ end;
+
+OnClock0000:
+ restoreshopitem Aquada, 20;
+OnClock0800:
+ restoreshopitem Aquada, 20;
+OnClock1600:
+ restoreshopitem Aquada, 20;
+}
+
+001-1,72,126,0 trader Store#SeaStore001-1 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem Aquada, -1, 10;
+ sellitem UrchinMeat, -1, 20;
+ sellitem SmallTentacles, -1, 30;
+ sellitem Tentacles, -1, 15;
+
+ .sex = G_OTHER;
+ .distance = 4;
+ end;
+
+OnClock0000:
+ restoreshopitem Aquada, 3;
+ restoreshopitem UrchinMeat, 12;
+ restoreshopitem SmallTentacles, 4;
+OnClock0800:
+ restoreshopitem Aquada, 6;
+ restoreshopitem UrchinMeat, 8;
+ restoreshopitem Tentacles, 8;
+ restoreshopitem SmallTentacles, 2;
+OnClock1600:
+ restoreshopitem Aquada, 5;
+ restoreshopitem UrchinMeat, 10;
+ restoreshopitem SmallTentacles, 7;
+}
+
+001-1,72,129,0 trader Store#FishStore001-1 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem CommonCarp, -1, 8;
+ sellitem GrassCarp, -1, 7;
+
+ .sex = G_OTHER;
+ .distance = 4;
+ end;
+
+OnClock0000:
+ restoreshopitem CommonCarp, 3;
+ restoreshopitem GrassCarp, 2;
+OnClock0800:
+ restoreshopitem CommonCarp, 2;
+ restoreshopitem GrassCarp, 3;
+OnClock1600:
+ restoreshopitem CommonCarp, 3;
+ restoreshopitem GrassCarp, 4;
+}
+
+001-1,48,116,0 trader Store#Manana001-1 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem Manana, -1, 60;
+
+ .sex = G_OTHER;
+ .distance = 4;
+ end;
+
+OnClock0000:
+ restoreshopitem Manana, 20;
+OnClock0800:
+ restoreshopitem Manana, 15;
+OnClock1600:
+ restoreshopitem Manana, 20;
+}
+
+001-1,53,123,0 trader Store#Various001-1 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem Manana, -1, 30;
+// Add soft drinks.
+
+ .sex = G_OTHER;
+ .distance = 4;
+ end;
+
+OnClock0000:
+ restoreshopitem Manana, 10;
+OnClock0800:
+ restoreshopitem Manana, 15;
+OnClock1600:
+ restoreshopitem Manana, 6;
+}
+
+001-1,67,116,0 trader Store#Potion001-1 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem PiberriesInfusion, -1, 200;
+ sellitem FatesPotion, -1, 100;
+ sellitem ClothoLiquor, -1, 50;
+ sellitem LachesisBrew, -1, 30;
+ sellitem AtroposMixture, -1, 10;
+ sellitem ElixirOfLife, -1, 2;
+
+ .sex = G_OTHER;
+ .distance = 4;
+ end;
+
+OnClock0000:
+ restoreshopitem PiberriesInfusion, 150;
+ restoreshopitem FatesPotion, 80;
+ restoreshopitem ClothoLiquor, 40;
+ restoreshopitem LachesisBrew, 20;
+ restoreshopitem AtroposMixture, 7;
+ restoreshopitem ElixirOfLife, 1;
+OnClock1200:
+ restoreshopitem PiberriesInfusion, 80;
+ restoreshopitem FatesPotion, 40;
+ restoreshopitem ClothoLiquor, 20;
+ restoreshopitem LachesisBrew, 10;
+ restoreshopitem AtroposMixture, 4;
+}
+
+001-1,58,119,0 trader Store#General001-1 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem Manana, -1, 100;
+ sellitem Carrot, -1, 80;
+ sellitem Aquada, -1, 50;
+ sellitem Plushroom, -1, 100;
+ sellitem Curshroom, -1, 80;
+ sellitem Piberries, -1, 150;
+ sellitem PiouEgg, -1, 25;
+// Add soft drinks.
+
+ .sex = G_OTHER;
+ .distance = 4;
+ end;
+
+OnClock0000:
+ restoreshopitem Manana, 50;
+ restoreshopitem Carrot, 40;
+ restoreshopitem Aquada, 30;
+ restoreshopitem Plushroom, 40;
+ restoreshopitem Curshroom, 30;
+ restoreshopitem Piberries, 40;
+ restoreshopitem PiouEgg, 10;
+OnClock0800:
+ restoreshopitem Manana, 30;
+ restoreshopitem Carrot, 30;
+ restoreshopitem Aquada, 30;
+ restoreshopitem Plushroom, 40;
+ restoreshopitem Curshroom, 30;
+ restoreshopitem Piberries, 70;
+ restoreshopitem PiouEgg, 10;
+OnClock1600:
+ restoreshopitem Manana, 40;
+ restoreshopitem Carrot, 40;
+ restoreshopitem Aquada, 20;
+ restoreshopitem Plushroom, 20;
+ restoreshopitem Curshroom, 20;
+ restoreshopitem Piberries, 30;
+ restoreshopitem PiouEgg, 5;
+}
diff --git a/npc/001-1/sign.txt b/npc/001-1/sign.txt
new file mode 100644
index 000000000..d489cc19f
--- /dev/null
+++ b/npc/001-1/sign.txt
@@ -0,0 +1,186 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Reid
+// Description:
+// Sign pillars aside Artis houses.
+
+001-1,73,119,0 script Sign#001-1-s-market NPC_NO_SPRITE,{
+ npctalkonce l("Market Place");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,48,122,0 script Sign#001-1-s-marketright NPC_NO_SPRITE,{
+ npctalkonce l("Market Place");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,57,88,0 script Sign#001-1-s-marketdir NPC_NO_SPRITE,{
+ npctalkonce l("↓ Market Place");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,55,86,0 script Sign#001-1-s-exit-l-dir NPC_NO_SPRITE,{
+ npctalkonce l("← Exit");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,59,85,0 script Sign#001-1-s-legiondir NPC_NO_SPRITE,{
+ npctalkonce l("↑ Legion");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,57,80,0 script Sign#001-1-s-library NPC_NO_SPRITE,{
+ npctalkonce l("Library");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,57,71,0 script Sign#001-1-s-lightarmor NPC_NO_SPRITE,{
+ npctalkonce l("Light Armor Shop");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,53,56,0 script Sign#001-1-s-legion NPC_OFFSET_NO_SPRITE,{
+ npctalkonce l("Legion of Aemil");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,60,56,0 script Sign#001-1-s-legionright NPC_OFFSET_NO_SPRITE,{
+ npctalkonce l("Legion of Aemil");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,91,66,0 script Sign#001-1-s-cityhall NPC_NO_SPRITE,{
+ npctalkonce l("City Hall");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,95,111,0 script Sign#001-1-s-blacksmith NPC_NO_SPRITE,{
+ npctalkonce l("Blacksmith");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,115,88,0 script Sign#001-1-s-inn NPC_NO_SPRITE,{
+ npctalkonce l("Inn");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,134,85,0 script Sign#001-1-s-innright NPC_OFFSET_NO_SPRITE,{
+ npctalkonce l("Inn");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,118,36,0 script Sign#001-1-s-merchantg NPC_NO_SPRITE,{
+ npctalkonce l("Merchant Guild");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,171,48,0 script Sign#001-1-s-hill NPC_OFFSET_NO_SPRITE,{
+ npctalkonce l("Hill & Cliff");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,161,72,0 script Sign#001-1-s-alchemist NPC_NO_SPRITE,{
+ npctalkonce l("Alchemist's Laboratory");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,175,76,0 script Sign#001-1-s-warehouse NPC_NO_SPRITE,{
+ npctalkonce l("Docks Warehouse");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
+
+001-1,47,97,0 script Sign#001-1-s-barber NPC_NO_SPRITE,{
+ npctalkonce l("Barber");
+ close;
+
+OnInit:
+ .distance = 1;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-1/taree.txt b/npc/001-1/taree.txt
new file mode 100644
index 000000000..5af18b0e2
--- /dev/null
+++ b/npc/001-1/taree.txt
@@ -0,0 +1,21 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Mouboo farmer.
+
+001-1,68,79,0 script Taree NPC_ELVEN_MAN_MOUBOO_SHOP,{
+ mesn;
+ mesq l("Moo!");
+
+ goto L_Close;
+
+L_Close:
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-1/treeleaf.txt b/npc/001-1/treeleaf.txt
new file mode 100644
index 000000000..dd1280a69
--- /dev/null
+++ b/npc/001-1/treeleaf.txt
@@ -0,0 +1,22 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Reid
+// Description:
+// Falling tree leaf
+
+001-1,39,54,4 script #treeleaf0 NPC_TREE_LEAF,{
+ .dir = 2;
+ stopnpctimer;
+ initnpctimer;
+ close;
+
+OnTimer2800:
+ .dir = 4;
+ stopnpctimer;
+ end;
+
+OnInit:
+ .distance = 1;
+ end;
+}
diff --git a/npc/001-1/trees.txt b/npc/001-1/trees.txt
new file mode 100644
index 000000000..cba42f8ff
--- /dev/null
+++ b/npc/001-1/trees.txt
@@ -0,0 +1,235 @@
+// Evol scripts.
+// Author:
+// Travolta
+// Description:
+// Invisible tree NPCs for "Lazy Brother" quest
+// Variables:
+// AtrilQuests_LazyBrother = 19 -- quest var
+// LazyBrother_TreesLeft = 15 -- how many trees left to search
+// LazyBrother_TreeSearched[15] -- whether given tree was searched
+// LazyBrother_TreeWithBrother -- the number of tree where he's hiding
+// Quest states:
+// 0 - quest not started
+// 1 - Katja asked help, searching the trees
+// 2 - Bobo is found, "bad" ending
+// 3 - player decided to tell Katja where her brother is
+// 4 - "good" ending, player helped Katja
+
+function script LazyBrotherTreeFunc {
+ .@q = getq(ArtisQuests_LazyBrother);
+ if (.@q == 0 || .@q >= 2)
+ return;
+ .@TreeNum = getarg(0);
+ if (LazyBrother_TreeWithBrother == .@TreeNum)
+ goto L_FoundHim;
+ if (LazyBrother_TreeWithBrother > 0)
+ {
+ mes l("You search the tree but don't find anybody.");
+ close2;
+ return;
+ }
+ if (LazyBrother_TreeSearched[.@TreeNum] == 1)
+ {
+ mes l("You already looked here.");
+ close2;
+ return;
+ }
+ else
+ {
+ LazyBrother_TreeSearched[.@TreeNum] = 1;
+ }
+ .@found = rand(1, LazyBrother_TreesLeft--);
+ if (.@found == 1)
+ {
+ mes l("You found him!");
+ LazyBrother_TreeWithBrother = .@TreeNum;
+ next;
+ }
+ else
+ {
+ mes l("You search the tree but don't find anybody.");
+ close2;
+ return;
+ }
+
+L_FoundHim:
+ mes l("You notice a young boy sitting on one of the highest branches of the tree.");
+ next;
+ mes l("He is eating an apple, thoroughly enjoying it.");
+ next;
+ select(l("Hey there, are you Bobo, Katja's brother?"));
+ mes "";
+ mesn "Bobo";
+ mesq l("Yes, it's me. It's such a fine view from here!");
+ next;
+ select(lg("Your sister sent me to find you. Your mother is worried."));
+ mes "";
+ mesn "Bobo";
+ mesq l("Oh, nooooo... If I go home now, my mum will give me chores.");
+ next;
+ mesq l("But if you tell my sister, that you didn't find me, I can stay here all day, eating apples and enjoying the view.");
+ next;
+ mesq l("I will give you my pocket money if you do.");
+ next;
+ switch (select(l("A small lie is really just a fib, and I could really use some cash..."),
+ l("I will not lie to a little girl! And your mother needs your help.")))
+ {
+ case 1:
+ mes "";
+ mesn "Bobo";
+ mesq l("Here you go.");
+ next;
+ mesn "Narrator";
+ mes l("Somehow you don't feel good about your deed.");
+ // Karma -= 2;
+ setq ArtisQuests_LazyBrother, 2;
+ Zeny += 100;
+ getexp 500, 0;
+ break;
+ case 2:
+ mes "";
+ mesn "Bobo";
+ mesq l("Okay... Tell my sister I'll go home soon.");
+ setq ArtisQuests_LazyBrother, 3;
+ break;
+ }
+ LazyBrother_TreesLeft = 0;
+ LazyBrother_TreeWithBrother = 0;
+ cleararray LazyBrother_TreeSearched,0,15;
+ close;
+}
+
+001-1,179,30,0 script #AtrilTree1 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(1);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,177,29,0 script #AtrilTree2 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(2);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,183,28,0 script #AtrilTree3 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(3);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,182,25,0 script #AtrilTree4 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(4);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,187,26,0 script #AtrilTree5 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(5);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,189,28,0 script #AtrilTree6 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(6);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,184,30,0 script #AtrilTree7 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(7);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,189,31,0 script #AtrilTree8 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(8);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,191,30,0 script #AtrilTree9 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(9);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,191,33,0 script #AtrilTree10 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(10);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,187,34,0 script #AtrilTree11 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(11);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,185,35,0 script #AtrilTree12 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(12);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,182,34,0 script #AtrilTree13 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(13);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,180,33,0 script #AtrilTree14 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(14);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-1,181,32,0 script #AtrilTree15 NPC_KATJA_TREE,{
+ LazyBrotherTreeFunc(15);
+ end;
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
diff --git a/npc/001-1/wateranimation.txt b/npc/001-1/wateranimation.txt
new file mode 100644
index 000000000..285a7788f
--- /dev/null
+++ b/npc/001-1/wateranimation.txt
@@ -0,0 +1,33 @@
+// Evol scripts.
+// Author:
+// gumi
+// Reid
+// Description:
+// Water animations, splash, fishes, etc...
+
+001-1,116,123,0 script #water_animation0 NPC_WATER_SPLASH,{
+
+ fishing; // begin or continue fishing
+ close;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 5;
+ end;
+}
+
+001-1,119,102,0 duplicate(#water_animation0) #water_animation1 NPC_WATER_SPLASH
+001-1,167,82,0 duplicate(#water_animation0) #water_animation2 NPC_WATER_SPLASH
+001-1,167,40,0 duplicate(#water_animation0) #water_animation3 NPC_WATER_SPLASH
+001-1,104,127,0 duplicate(#water_animation0) #water_animation4 NPC_WATER_SPLASH
+001-1,166,123,0 duplicate(#water_animation0) #water_animation5 NPC_WATER_SPLASH
+001-1,181,119,0 duplicate(#water_animation0) #water_animation6 NPC_WATER_SPLASH
+001-1,202,114,0 duplicate(#water_animation0) #water_animation7 NPC_WATER_SPLASH
+001-1,187,86,0 duplicate(#water_animation0) #water_animation8 NPC_WATER_SPLASH
+001-1,32,57,0 duplicate(#water_animation0) #water_animation9 NPC_WATER_SPLASH
+001-1,40,144,0 duplicate(#water_animation0) #water_animation10 NPC_WATER_SPLASH
+001-1,58,131,0 duplicate(#water_animation0) #water_animation11 NPC_WATER_SPLASH
+001-1,76,137,0 duplicate(#water_animation0) #water_animation12 NPC_WATER_SPLASH
+001-1,109,132,0 duplicate(#water_animation0) #water_animation13 NPC_WATER_SPLASH
+001-1,141,93,0 duplicate(#water_animation0) #water_animation14 NPC_WATER_SPLASH
+001-1,168,57,0 duplicate(#water_animation0) #water_animation15 NPC_WATER_SPLASH
diff --git a/npc/001-1/xilaxa.txt b/npc/001-1/xilaxa.txt
new file mode 100644
index 000000000..5b7ec398a
--- /dev/null
+++ b/npc/001-1/xilaxa.txt
@@ -0,0 +1,67 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Moon, main NPC for the urchin quest.
+
+001-1,52,44,0 script Xilaxa#001-1 NPC_UKAR_MALE_LEGION_ARTIS,{
+
+ function face_to_PC {
+ getmapxy(.@map$, .@cx, .@cy, 0);
+ @Devis_old_dir = .dir;
+ npc_turntoxy(.@cx, .@cy);
+
+ return;
+ }
+
+ function local_close {
+ if (@Devis_old_dir != .dir)
+ {
+ .dir = @Devis_old_dir;
+ }
+ npc_resumemove;
+
+ close;
+ }
+
+ npc_pausemove;
+ face_to_PC;
+ npctalkonce goodbye_msg();
+ local_close;
+
+OnTimer1000:
+ dographmovestep;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 5;
+ initmovegraph "mid", 54, 43, 60, 46,
+ "left", 47, 50, 52, 55,
+ "right", 62, 50, 67, 55;
+
+ setmovegraphcmd "mid", "left", 1, "dir 0; wait 4",
+ "mid", "left", 4, "dir 2; wait 3; dir 0; wait 2; dir 6; wait 1; dir 0",
+ "mid", "left", 2, "dir 4; wait 5; dir 0; wait 2",
+ "mid", "left", 3, "dir 6; wait 1; dir 0; wait 3; dir 2; wait 3; dir 0",
+ "mid", "left", 1, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5",
+ "mid", "right", 3, "dir 0; wait 4",
+ "mid", "right", 4, "dir 2; wait 3; dir 0; wait 2; dir 6; wait 1; dir 0",
+ "mid", "right", 2, "dir 4; wait 5; dir 0; wait 2",
+ "mid", "right", 1, "dir 6; wait 1; dir 0; wait 3; dir 2; wait 3; dir 0",
+ "mid", "right", 2, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5",
+
+ "left", "mid", 2, "dir 0; wait 4",
+ "left", "mid", 1, "dir 2; wait 3; dir 0; wait 2; dir 6; wait 1; dir 0",
+ "left", "mid", 3, "dir 4; wait 5; dir 0; wait 2",
+ "left", "mid", 2, "dir 6; wait 1; dir 0; wait 3; dir 2; wait 3; dir 0",
+ "left", "mid", 3, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5",
+
+ "right", "mid", 3, "dir 0; wait 4",
+ "right", "mid", 2, "dir 2; wait 3; dir 0; wait 2; dir 6; wait 1; dir 0",
+ "right", "mid", 1, "dir 4; wait 5; dir 0; wait 2",
+ "right", "mid", 1, "dir 6; wait 1; dir 0; wait 3; dir 2; wait 3; dir 0",
+ "right", "mid", 2, "dir 0; wait 1; dir 2; wait 1; dir 0; wait 1; dir 6; wait 5";
+
+ firstmove "wait 5", "mid";
+ initnpctimer;
+}
diff --git a/npc/001-2-0/_import.txt b/npc/001-2-0/_import.txt
new file mode 100644
index 000000000..2fb6a2627
--- /dev/null
+++ b/npc/001-2-0/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-0: Light Armor Shop
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-0/_warps.txt",
+"npc/001-2-0/mapflags.txt",
+"npc/001-2-0/resa.txt",
+"npc/001-2-0/shop.txt",
diff --git a/npc/001-2-0/_warps.txt b/npc/001-2-0/_warps.txt
new file mode 100644
index 000000000..c81b7fa6b
--- /dev/null
+++ b/npc/001-2-0/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-0: Light Armor Shop warps
+001-2-0,30,35,0 warp #001-2-0_30_35 0,0,001-1,51,66
+001-2-0,37,46,0 warp #001-2-0_37_46 0,0,001-1,55,72
diff --git a/npc/001-2-0/mapflags.txt b/npc/001-2-0/mapflags.txt
new file mode 100644
index 000000000..a1781431f
--- /dev/null
+++ b/npc/001-2-0/mapflags.txt
@@ -0,0 +1 @@
+001-2-0 mapflag town
diff --git a/npc/001-2-0/resa.txt b/npc/001-2-0/resa.txt
new file mode 100644
index 000000000..1530c8617
--- /dev/null
+++ b/npc/001-2-0/resa.txt
@@ -0,0 +1,80 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Light Armor shop keeper.
+// Variables:
+// ArtisQuests_Enora
+// Values:
+// 0 Default.
+// 1 BlackSmith quest delivered.
+// 2 Chelios Quest given.
+// 3 Chelios Quest done.
+// 4 BlackSmith gave the sword.
+// 5 Light Armor Shop quest delivered.
+// 6 Light Armor Shop gave the cloths.
+
+001-2-0,37,28,0 script Resa NPC_ELVEN_FEMALE_ARMOR_SHOP,{
+
+ function explain_craft {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Did you see Don the blacksmith? He might know how you could improve your metal equipment."),
+ l("Nevertheless, you can craft some cards that you can then attach to your equipment."),
+ l("We sell a brimmed hat, you can craft a feather card and attach it to this hat to obtain an enhanced version of it!");
+
+ return;
+ }
+
+ function enora_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I thought that she would never come to pick it up!"),
+ l("Here it is, a fashionable @@.", getitemlink(ArtisTankTop, CamelCottonDye)),
+ l("I asked Calypsan to dye this tank top, now it has an unique look!");
+
+ narrator S_LAST_NEXT, l("You pick up the package.");
+
+ setq ArtisQuests_Enora, 6;
+
+ return;
+ }
+
+ speech S_LAST_NEXT,
+ l("Welcome to my office."),
+ l("What would you like today?");
+
+ do
+ {
+ .@enora = getq(ArtisQuests_Enora);
+ select
+ rif(.@enora == 5, lg("I came to retrieve a package for Enora.")),
+ menuaction(l("Trade")),
+ l("How can I improve my equipment?"),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ enora_quest;
+ closedialog;
+ goodbye;
+ close;
+ case 2:
+ closedialog;
+ shop "Store#001-2-0";
+ close;
+ case 3:
+ explain_craft;
+ break;
+ case 4:
+ closedialog;
+ goodbye;
+ close;
+ }
+ } while (1);
+
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-0/shop.txt b/npc/001-2-0/shop.txt
new file mode 100644
index 000000000..9fe97b17e
--- /dev/null
+++ b/npc/001-2-0/shop.txt
@@ -0,0 +1,35 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Light armor shop.
+
+001-2-0,37,29,0 trader Store#001-2-0 NPC_NO_SPRITE,{
+// The ArtisTankTop should be store at x: 39 or 40, y: 31.
+// 38,35 is server's location of where client displays a black torso gear on display. (using @where for server).
+// 35,27 is some shelves and a cabinet at 4 tiles from where player select it.
+// 39,27 is where to put store that sells only fabric. (the cloth shelf).
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem ArtisTankTop, -1, 50;
+ sellitem VneckJumper, -1, 30;
+ sellitem BrownTrousers, -1, 30;
+ sellitem BrimmedHat, -1, 35;
+
+ .sex = G_OTHER;
+ .distance = 2;
+ end;
+
+OnClock0000:
+ restoreshopitem ArtisTankTop, 30;
+ restoreshopitem VneckJumper, 12;
+ restoreshopitem BrownTrousers, 15;
+ restoreshopitem BrimmedHat, 10;
+OnClock1200:
+ restoreshopitem ArtisTankTop, 25;
+ restoreshopitem VneckJumper, 10;
+ restoreshopitem BrownTrousers, 10;
+ restoreshopitem BrimmedHat, 20;
+}
diff --git a/npc/001-2-1/_import.txt b/npc/001-2-1/_import.txt
new file mode 100644
index 000000000..859332420
--- /dev/null
+++ b/npc/001-2-1/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-1: Noble House
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-1/_savepoints.txt",
+"npc/001-2-1/_warps.txt",
+"npc/001-2-1/mapflags.txt",
diff --git a/npc/001-2-1/_savepoints.txt b/npc/001-2-1/_savepoints.txt
new file mode 100644
index 000000000..4b3f1497b
--- /dev/null
+++ b/npc/001-2-1/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-1: Noble House saves
+001-2-1,27,30,0 script #save_001-2-1_27_30 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-2-1/_warps.txt b/npc/001-2-1/_warps.txt
new file mode 100644
index 000000000..1189adc73
--- /dev/null
+++ b/npc/001-2-1/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-1: Noble House warps
+001-2-1,37,41,0 warp #001-2-1_37_41 0,0,001-1,128,31
diff --git a/npc/001-2-1/mapflags.txt b/npc/001-2-1/mapflags.txt
new file mode 100644
index 000000000..07cacd147
--- /dev/null
+++ b/npc/001-2-1/mapflags.txt
@@ -0,0 +1 @@
+001-2-1 mapflag town
diff --git a/npc/001-2-10/_import.txt b/npc/001-2-10/_import.txt
new file mode 100644
index 000000000..7c1b01d6e
--- /dev/null
+++ b/npc/001-2-10/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-10: Noble House
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-10/_savepoints.txt",
+"npc/001-2-10/_warps.txt",
+"npc/001-2-10/mapflags.txt",
diff --git a/npc/001-2-10/_savepoints.txt b/npc/001-2-10/_savepoints.txt
new file mode 100644
index 000000000..c98aa4502
--- /dev/null
+++ b/npc/001-2-10/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-10: Noble House saves
+001-2-10,26,30,0 script #save_001-2-10_26_30 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-2-10/_warps.txt b/npc/001-2-10/_warps.txt
new file mode 100644
index 000000000..e9e39231f
--- /dev/null
+++ b/npc/001-2-10/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-10: Noble House warps
+001-2-10,27,45,0 warp #001-2-10_27_45 0,0,001-1,118,50
+001-2-10,51,45,0 warp #001-2-10_51_45 0,0,001-1,135,50
diff --git a/npc/001-2-10/mapflags.txt b/npc/001-2-10/mapflags.txt
new file mode 100644
index 000000000..bf8336096
--- /dev/null
+++ b/npc/001-2-10/mapflags.txt
@@ -0,0 +1 @@
+001-2-10 mapflag town
diff --git a/npc/001-2-11/_import.txt b/npc/001-2-11/_import.txt
new file mode 100644
index 000000000..7e5ac1009
--- /dev/null
+++ b/npc/001-2-11/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-11: Noble House
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-11/_savepoints.txt",
+"npc/001-2-11/_warps.txt",
+"npc/001-2-11/mapflags.txt",
+"npc/001-2-11/mona.txt",
diff --git a/npc/001-2-11/_savepoints.txt b/npc/001-2-11/_savepoints.txt
new file mode 100644
index 000000000..fc0b47fbe
--- /dev/null
+++ b/npc/001-2-11/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-11: Noble House saves
+001-2-11,26,31,0 script #save_001-2-11_26_31 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-2-11/_warps.txt b/npc/001-2-11/_warps.txt
new file mode 100644
index 000000000..648faa57c
--- /dev/null
+++ b/npc/001-2-11/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-11: Noble House warps
+001-2-11,46,46,0 warp #001-2-11_46_46 0,0,001-1,148,55
diff --git a/npc/001-2-11/mapflags.txt b/npc/001-2-11/mapflags.txt
new file mode 100644
index 000000000..608ef1bdb
--- /dev/null
+++ b/npc/001-2-11/mapflags.txt
@@ -0,0 +1 @@
+001-2-11 mapflag town
diff --git a/npc/001-2-11/mona.txt b/npc/001-2-11/mona.txt
new file mode 100644
index 000000000..e94fcc690
--- /dev/null
+++ b/npc/001-2-11/mona.txt
@@ -0,0 +1,67 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// A rich girl holding a candle.
+// Variable:
+// ArtisQuests_MonaDad
+// Quest states:
+// 0 - Quest not started
+// 1 - Mona explained that her dad was missing
+
+001-2-11,39,30,0 script Mona NPC_MONA,{
+
+ function find_daddy_quest
+ {
+ speech S_LAST_NEXT,
+ l("Hey you!");
+
+ switch (select(l("Yes?"), l("Sorry, I have to go.")))
+ {
+ case 1:
+ mes "";
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("No you don't have to go. I need your help, so you have to stay.");
+ break;
+ }
+
+ speech S_LAST_NEXT | S_NO_NPC_NAME,
+ l("Daddy did not come back home... He said that he would be back for lunch but it has already been a week!"),
+ l("You have to find him, or else I will tell him that you did not help me.");
+
+ switch (select(l("You do not give me much options."), l("The elder ran away from you.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE,
+ l("He said that he would check why the manhole next to the house was doing weird sounds."),
+ l("But he never returned."),
+ l("Please find my daddy...");
+
+ setq ArtisQuests_MonaDad, 1;
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE,
+ l("I will tell my dad!");
+ break;
+ }
+ emotion E_SAD;
+ close;
+ }
+
+ if (getq(ArtisQuests_MonaDad) == 0)
+ {
+ find_daddy_quest();
+ }
+
+ npctalkonce l("Please find daddy...");
+
+ emotion E_SAD;
+ close;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-12/_import.txt b/npc/001-2-12/_import.txt
new file mode 100644
index 000000000..fa40eb2b4
--- /dev/null
+++ b/npc/001-2-12/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-12: Noble House
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-12/_warps.txt",
+"npc/001-2-12/mapflags.txt",
+"npc/001-2-12/oscar.txt",
diff --git a/npc/001-2-12/_warps.txt b/npc/001-2-12/_warps.txt
new file mode 100644
index 000000000..c03a6b0bd
--- /dev/null
+++ b/npc/001-2-12/_warps.txt
@@ -0,0 +1,5 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-12: Noble House warps
+001-2-12,27,27,0 warp #001-2-12_27_27 1,0,001-2-13,27,29
+001-2-12,34,36,0 warp #001-2-12_34_36 0,0,001-1,142,31
+001-2-12,29,28,0 warp #001-2-12_29_28 0,0,001-2-14,25,29
diff --git a/npc/001-2-12/mapflags.txt b/npc/001-2-12/mapflags.txt
new file mode 100644
index 000000000..a84ff9382
--- /dev/null
+++ b/npc/001-2-12/mapflags.txt
@@ -0,0 +1 @@
+001-2-12 mapflag town
diff --git a/npc/001-2-12/oscar.txt b/npc/001-2-12/oscar.txt
new file mode 100644
index 000000000..3beecf36b
--- /dev/null
+++ b/npc/001-2-12/oscar.txt
@@ -0,0 +1,145 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Old man living in the rich hill, can bleach clothes.
+
+001-2-12,38,30,0 script Oscar#001-2-12 NPC_OSCAR,{
+
+ function live_here_alone
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Meh!"),
+ l("This is a harsh word to use, you are never alone in the beautiful place of Artis."),
+ l("Mob is doing its daily noise, nature is singing its sumptuous melody, none is alone.");
+
+ return;
+ }
+
+ function item_is_bleachable
+ {
+ .@item_index = getarg(0);
+ if (.@item_index < 0)
+ return false;
+
+ getinventorylist;
+
+ if (@inventorylist_card1[.@item_index] != 0)
+ {
+ if ((@inventorylist_card1[.@item_index] > YellowCottonDye) ||
+ (@inventorylist_card1[.@item_index] < CrimsonCashmereDye))
+ {
+ return false;
+ }
+ .@is_bleachable = true;
+ }
+ if (@inventorylist_card2[.@item_index] != 0)
+ {
+ if ((@inventorylist_card2[.@item_index] > YellowCottonDye) ||
+ (@inventorylist_card2[.@item_index] < CrimsonCashmereDye))
+ {
+ return false;
+ }
+ .@is_bleachable = true;
+ }
+ if (@inventorylist_card3[.@item_index] != 0)
+ {
+ if ((@inventorylist_card3[.@item_index] > YellowCottonDye) ||
+ (@inventorylist_card3[.@item_index] < CrimsonCashmereDye))
+ {
+ return false;
+ }
+ .@is_bleachable = true;
+ }
+ if (@inventorylist_card4[.@item_index] != 0)
+ {
+ if ((@inventorylist_card4[.@item_index] > YellowCottonDye) ||
+ (@inventorylist_card4[.@item_index] < CrimsonCashmereDye))
+ {
+ return false;
+ }
+ .@is_bleachable = true;
+ }
+
+ return .@is_bleachable;
+ }
+
+ function remove_cards_from_item
+ {
+ .@item_index = -1;
+
+ speech S_FIRST_BLANK_LINE,
+ l("What item would you like to bleach?");
+
+ narrator S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You can drag and drop an item to the NPC window or select an item through your inventory.");
+
+ .@item_index = requestitemindex();
+ if (!item_is_bleachable(.@item_index))
+ {
+ speech S_LAST_NEXT,
+ l("You should know this, an item like this can't be bleached.");
+
+ return;
+ }
+
+ speech S_LAST_NEXT,
+ l("Your mind is set? You will loose the color dye during this process.");
+
+ switch (askyesno())
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Ok, let me see..."),
+ l("...");
+
+ failedremovecardsindex .@item_index, 1;
+
+ speech S_LAST_NEXT | S_NO_NPC_NAME,
+ l("..."),
+ l("Here it is, clean like a whistle!");
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Is it truly a hard choice to make?");
+ break;
+ }
+
+ return;
+ }
+
+ .@hour = gettime(GETTIME_HOUR);
+ speech S_LAST_NEXT, (.@hour > 6 && .@hour < 18) ? l("Good day to you.") : lg("Good night milady.", "Good evening sir.");
+
+ do
+ {
+ select
+ l("Could you bleach my clothes?"),
+ l("Do you live here alone?"),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ remove_cards_from_item();
+ break;
+ case 2:
+ live_here_alone();
+ break;
+ case 3:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("I wish you a good time in town.");
+ break;
+ }
+
+ } while (@menu != 3);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-2-13/_import.txt b/npc/001-2-13/_import.txt
new file mode 100644
index 000000000..36eee751f
--- /dev/null
+++ b/npc/001-2-13/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-13: First Floor
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-13/_savepoints.txt",
+"npc/001-2-13/_warps.txt",
+"npc/001-2-13/mapflags.txt",
diff --git a/npc/001-2-13/_savepoints.txt b/npc/001-2-13/_savepoints.txt
new file mode 100644
index 000000000..dd2105262
--- /dev/null
+++ b/npc/001-2-13/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-13: First Floor saves
+001-2-13,41,31,0 script #save_001-2-13_41_31 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-2-13/_warps.txt b/npc/001-2-13/_warps.txt
new file mode 100644
index 000000000..9400dd8a5
--- /dev/null
+++ b/npc/001-2-13/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-13: First Floor warps
+001-2-13,27,30,0 warp #001-2-13_27_30 1,0,001-2-12,27,28
diff --git a/npc/001-2-13/mapflags.txt b/npc/001-2-13/mapflags.txt
new file mode 100644
index 000000000..329eb0544
--- /dev/null
+++ b/npc/001-2-13/mapflags.txt
@@ -0,0 +1 @@
+001-2-13 mapflag town
diff --git a/npc/001-2-14/_import.txt b/npc/001-2-14/_import.txt
new file mode 100644
index 000000000..0b4d600c5
--- /dev/null
+++ b/npc/001-2-14/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-2-14: Basement
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-14/_warps.txt",
+"npc/001-2-14/mapflags.txt",
diff --git a/npc/001-2-14/_warps.txt b/npc/001-2-14/_warps.txt
new file mode 100644
index 000000000..92dff8924
--- /dev/null
+++ b/npc/001-2-14/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-14: Basement warps
+001-2-14,26,29,0 warp #001-2-14_26_27 1,0,001-2-12,30,28
diff --git a/npc/001-2-14/mapflags.txt b/npc/001-2-14/mapflags.txt
new file mode 100644
index 000000000..a84ff9382
--- /dev/null
+++ b/npc/001-2-14/mapflags.txt
@@ -0,0 +1 @@
+001-2-12 mapflag town
diff --git a/npc/001-2-15/_import.txt b/npc/001-2-15/_import.txt
new file mode 100644
index 000000000..d4250125d
--- /dev/null
+++ b/npc/001-2-15/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-15: Noble House
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-15/_savepoints.txt",
+"npc/001-2-15/_warps.txt",
+"npc/001-2-15/mapflags.txt",
diff --git a/npc/001-2-15/_savepoints.txt b/npc/001-2-15/_savepoints.txt
new file mode 100644
index 000000000..c8b825618
--- /dev/null
+++ b/npc/001-2-15/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-15: Noble House saves
+001-2-15,27,41,0 script #save_001-2-15_27_41 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-2-15/_warps.txt b/npc/001-2-15/_warps.txt
new file mode 100644
index 000000000..5704aecca
--- /dev/null
+++ b/npc/001-2-15/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-15: Noble House warps
+001-2-15,34,46,0 warp #001-2-15_34_46 0,0,001-1,132,68
diff --git a/npc/001-2-15/mapflags.txt b/npc/001-2-15/mapflags.txt
new file mode 100644
index 000000000..5ff9ed8da
--- /dev/null
+++ b/npc/001-2-15/mapflags.txt
@@ -0,0 +1 @@
+001-2-15 mapflag town
diff --git a/npc/001-2-16/_import.txt b/npc/001-2-16/_import.txt
new file mode 100644
index 000000000..66b975ca7
--- /dev/null
+++ b/npc/001-2-16/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-2-16: Harbourmaster Lodge
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-16/_warps.txt",
+"npc/001-2-16/mapflags.txt",
diff --git a/npc/001-2-16/_warps.txt b/npc/001-2-16/_warps.txt
new file mode 100644
index 000000000..ba8035ee8
--- /dev/null
+++ b/npc/001-2-16/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-16: Harbourmaster Lodge warps
+001-2-16,32,36,0 warp #001-2-16_32_36 0,0,001-1,168,99
+001-2-16,24,29,0 warp #001-2-16_24_29 0,0,001-2-17,35,29
diff --git a/npc/001-2-16/mapflags.txt b/npc/001-2-16/mapflags.txt
new file mode 100644
index 000000000..44cfc0a15
--- /dev/null
+++ b/npc/001-2-16/mapflags.txt
@@ -0,0 +1 @@
+001-2-16 mapflag town
diff --git a/npc/001-2-17/_import.txt b/npc/001-2-17/_import.txt
new file mode 100644
index 000000000..ef22e0df8
--- /dev/null
+++ b/npc/001-2-17/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-2-17: Backroom
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-17/_warps.txt",
+"npc/001-2-17/mapflags.txt",
diff --git a/npc/001-2-17/_warps.txt b/npc/001-2-17/_warps.txt
new file mode 100644
index 000000000..b2f5355ec
--- /dev/null
+++ b/npc/001-2-17/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-17: Backroom warps
+001-2-17,36,29,0 warp #001-2-17_36_29 0,0,001-2-16,25,29
diff --git a/npc/001-2-17/mapflags.txt b/npc/001-2-17/mapflags.txt
new file mode 100644
index 000000000..ae59a3773
--- /dev/null
+++ b/npc/001-2-17/mapflags.txt
@@ -0,0 +1 @@
+001-2-17 mapflag town
diff --git a/npc/001-2-18/_import.txt b/npc/001-2-18/_import.txt
new file mode 100644
index 000000000..a29300849
--- /dev/null
+++ b/npc/001-2-18/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-2-18: Docks Warehouse
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-18/_warps.txt",
+"npc/001-2-18/mapflags.txt",
diff --git a/npc/001-2-18/_warps.txt b/npc/001-2-18/_warps.txt
new file mode 100644
index 000000000..e03422399
--- /dev/null
+++ b/npc/001-2-18/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-18: Docks Warehouse warps
+001-2-18,39,36,0 warp #001-2-18_39_36 0,0,001-1,182,75
+001-2-18,39,26,0 warp #001-2-18_39_26 2,0,001-2-42,39,36
diff --git a/npc/001-2-18/mapflags.txt b/npc/001-2-18/mapflags.txt
new file mode 100644
index 000000000..db4e14335
--- /dev/null
+++ b/npc/001-2-18/mapflags.txt
@@ -0,0 +1 @@
+001-2-18 mapflag town
diff --git a/npc/001-2-19/_import.txt b/npc/001-2-19/_import.txt
new file mode 100644
index 000000000..c92d08258
--- /dev/null
+++ b/npc/001-2-19/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-19: Merchant Hall
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-19/_warps.txt",
+"npc/001-2-19/lloyd.txt",
+"npc/001-2-19/mapflags.txt",
diff --git a/npc/001-2-19/_warps.txt b/npc/001-2-19/_warps.txt
new file mode 100644
index 000000000..fa0917193
--- /dev/null
+++ b/npc/001-2-19/_warps.txt
@@ -0,0 +1,51 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-19: Merchant Hall warps
+001-2-19,41,31,0 warp #001-2-19_41_31 0,0,001-1,104,33
+001-2-19,41,24,0 script #001-2-19_41_24_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-25", 29, 30;
+close;
+
+OnUnTouch:
+ doevent "#001-2-19_41_24::OnUnTouch";
+}
+001-2-19,41,24,0 script #001-2-19_41_24 NPC_ARTIS_DOOR_WOOD,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-2-19,33,38,0 warp #001-2-19_33_38 0,0,001-1,101,37
+001-2-19,41,57,0 warp #001-2-19_41_55 0,0,001-2-20,29,27
+001-2-19,41,47,0 script #001-2-19_41_47_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-1", 104, 42;
+close;
+
+OnUnTouch:
+ doevent "#001-2-19_41_47::OnUnTouch";
+}
+001-2-19,41,47,0 script #001-2-19_41_47 NPC_ARTIS_DOOR_WOOD,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
diff --git a/npc/001-2-19/lloyd.txt b/npc/001-2-19/lloyd.txt
new file mode 100644
index 000000000..9a0b2f37c
--- /dev/null
+++ b/npc/001-2-19/lloyd.txt
@@ -0,0 +1,244 @@
+// Evol scripts.
+// Authors:
+// gumi
+// Reid
+// Description:
+// Lloyd the banker NPC.
+// Variables:
+// 0 ArtisQuests_Lloyd
+// 1 ArtisQuests_Fexil
+// 2 ArtisQuests_Enora
+// Quest states:
+// 00 -- Never talked
+// 01 -- Registred on the Guild
+// 10 -- not started
+// 11 -- Lloyd warned about the quest
+// 20 -- Default.
+// 21 -- BlackSmith quest delivered.
+// 22 -- Chelios Quest given.
+// 23 -- Chelios Quest done.
+
+001-2-19,31,25,0 script Lloyd the Banker NPC_LLOYD,{
+
+ function enora_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Black iron... That is a very specific request that you have for me!"),
+ l("Let me check in my inventory book..."),
+ l("..."),
+ l("Yes, I have some! \"5x Black Iron Ingots\""),
+ lg("Is this for you or somebody else? Because you need to be registered to obtain these materials.");
+
+ switch (selectd(ArtisQuests_Enora,
+ l("This is for my own use."),
+ l("Chelios asked me to get it.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE,
+ l("This is your first time asking for something, you won't pay this time, take it as a sign of good faith!"),
+ l("If you need something in the future, do not hesitate to pass by here, our stock is full of boxes collecting dust.");
+ emotion E_WINK;
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE,
+ l("Chelios... He is part of the Blacksmith House, is he not?"),
+ l("Since Don settled in Artis he and his band refused to register to the Merchant Guild."),
+ l("I will close an eye for once, but only because it's your first time asking for something!"),
+ l("Sometimes a good merchant needs to reach out first. It's on the house, give Chelios my regards!");
+ emotion E_WINK;
+ break;
+ }
+ setq ArtisQuests_Enora, 3;
+
+ return;
+ }
+
+ function explain_guild {
+ speech S_LAST_NEXT,
+ l("The guild is in charge of the commerce regularization throughout Artis and its surroundings."),
+ l("With the help of the town hall and the Legion of Aemil we organize some auction and we help local merchants to launch their businesses."),
+ l("We also feature some services like a storage and a bank for members."),
+ l("Registration is open to everybody, but newcomers need to pay a fee for all of the paperwork.");
+
+ narrator S_FIRST_BLANK_LINE,
+ l("The bank and item storage is shared between all characters within a same account."),
+ l("With it, you can safely move items and funds between your characters."),
+ l("To move between characters that are on different accounts, you have to use the Trade function.");
+ return;
+ }
+
+ function first_visit {
+ speech S_LAST_NEXT,
+ l("Welcome!"),
+ l("My name is Lloyd, I am a representative of the Merchant Guild of Artis.");
+
+ selectd(l("My name is @@...", strcharinfo(0)));
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("\"@@\", I like this name!", strcharinfo(0)),
+ l("Oh, wait a second...");
+ narrator S_LAST_NEXT,
+ l("Lloyd is searching something in his book.");
+ speech S_LAST_NEXT,
+ l("I see."),
+ lg("You are new around here, right?");
+
+ if (selectd(l("How do you know?"), l("Yes I am.")) == 1)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh, it is simple. I have on this book the names of every citizen of Artis and its surroundings."),
+ l("And I have no mention of a so called \"@@\" on it!", strcharinfo(0));
+ }
+ else
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I knew it!");
+ }
+
+ speech S_LAST_NEXT,
+ l("Let me explain to you what the Merchant Guild is for.");
+
+ explain_guild;
+ next;
+
+ .@price = 500;
+ speech S_LAST_NEXT,
+ l("The fee is of @@ E. So, do you want to register?", .@price);
+
+ switch (selectd(l("Yes."),
+ l("I don't have the time now.")))
+ {
+ case 1:
+ if (Zeny < .@price)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You do not seem to have enough money, come back later!");
+ }
+ else
+ {
+ Zeny = Zeny - .@price;
+ setq ArtisQuests_Lloyd, 1;
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Perfect!"),
+ l("I wrote your name on the book, you are now free to use the storage and bank services.");
+ }
+ break;
+ case 2:
+ break;
+ }
+
+ return;
+ }
+
+ function paper_to_deliver {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Now that you bring up that topic, that reminds me of something..."),
+ l("Earlier today there was this young seller named Fexil that passed by here."),
+ l("He asked to lend some money and a place to open his store, I think that he asked for a place on the merchant squares on the south-west of the city..."),
+ l("Anyway, he forgot his permit when he left the building."),
+ l("Could you bring it to him?");
+
+ do
+ {
+ .@q = selectd(ArtisQuests_Fexil,
+ l("Ok, I will bring it to him."),
+ l("I need more information first."),
+ l("I don't have the time."));
+ switch (.@q)
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Thank you for this!");
+ setq ArtisQuests_Fexil, 1;
+ break;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You should look for a seller named Fexil around the merchant square."),
+ l("Ask other merchants, they might know where he is.");
+ break;
+ case 3:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("No problem, come back later if you changed your mind!");
+ break;
+ }
+ } while (.@q == 2);
+ }
+
+ if (getq(ArtisQuests_Lloyd) == 0)
+ {
+ first_visit;
+
+ closedialog;
+ goodbye;
+ close;
+ }
+
+ speech S_LAST_NEXT,
+ l("Welcome to the Merchant Guild of Artis!"),
+ l("What do you want today?");
+
+ do
+ {
+ .@enora = getq(ArtisQuests_Enora);
+
+ selectd
+ rif(.@enora == 2, l("I'm looking for some black iron ingots.")),
+ l("I would like to store some items."),
+ l("I would like to perform money transactions."),
+ l("What is this guild for?"),
+ l("Does the guild has any work for me right now?"),
+ l("Bye.");
+
+ switch (@menu)
+ {
+ case 1:
+ enora_quest;
+ break;
+ case 2:
+ openstorage;
+ closedialog;
+ close;
+ break;
+ case 3:
+ MerchantGuild_Bank;
+ break;
+ case 4:
+ mes "";
+ explain_guild;
+ break;
+ case 5:
+ if (getq(ArtisQuests_Fexil) >= 1)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("There are no tasks for you right now.");
+ continue;
+ }
+
+ paper_to_deliver;
+
+ continue;
+ }
+ if (@menu != 6)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT | S_NO_NPC_NAME,
+ l("Something else?");
+ }
+ } while (@menu != 6);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .quest_debug = ArtisQuests_Lloyd;
+ .sex = G_MALE;
+ .distance = 4;
+ end;
+
+OnPCLoginEvent:
+ if (#MerchantBank)
+ {
+ BankVault += max(0, #MerchantBank);
+ #MerchantBank = 0;
+ }
+ end;
+}
diff --git a/npc/001-2-19/mapflags.txt b/npc/001-2-19/mapflags.txt
new file mode 100644
index 000000000..f083b6eb9
--- /dev/null
+++ b/npc/001-2-19/mapflags.txt
@@ -0,0 +1 @@
+001-2-19 mapflag town
diff --git a/npc/001-2-2/_import.txt b/npc/001-2-2/_import.txt
new file mode 100644
index 000000000..7d11248ec
--- /dev/null
+++ b/npc/001-2-2/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-2: Moon's House
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-2/_warps.txt",
+"npc/001-2-2/mapflags.txt",
+"npc/001-2-2/moon.txt",
diff --git a/npc/001-2-2/_warps.txt b/npc/001-2-2/_warps.txt
new file mode 100644
index 000000000..f28c931d1
--- /dev/null
+++ b/npc/001-2-2/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-2: Moon's House warps
+001-2-2,38,39,0 warp #001-2-2_38_39 0,0,001-1,70,78
+001-2-2,27,29,0 warp #001-2-2_27_29 2,0,001-2-3,27,30
diff --git a/npc/001-2-2/mapflags.txt b/npc/001-2-2/mapflags.txt
new file mode 100644
index 000000000..ff5a8f27b
--- /dev/null
+++ b/npc/001-2-2/mapflags.txt
@@ -0,0 +1 @@
+001-2-2 mapflag town
diff --git a/npc/001-2-2/moon.txt b/npc/001-2-2/moon.txt
new file mode 100644
index 000000000..ea76d3b73
--- /dev/null
+++ b/npc/001-2-2/moon.txt
@@ -0,0 +1,214 @@
+// Evol scripts.
+// Authors:
+// Reid
+// Travolta
+// Description:
+// Moon, main NPC for the urchin quest.
+// Variables:
+// ArtisQuests_Urchin - quest var
+// Quest stages:
+// 0 - not started
+// 1 - started, searching for Croc Claws
+// 2 - quest finished
+
+001-2-2,33,32,0 script Moon#001-2-2 NPC_ELVEN_FEMALE,3,3,{
+
+ function SayRandomGreeting {
+ .@q = getq(ArtisQuests_Urchin);
+ .@tick = gettimetick(1);
+ if (.@tick > @ArtisQuests_Urchin_MoonMsgTick + 12)
+ {
+ setarray .messages$[0], l("Ouch!"), l("It hurts so bad!"),
+ l("Help me!"), l("Hurry up!"),
+ l("I can't wait all day!"),
+ l("I need more Croc Claws."),
+ l("What a relief."),
+ l("No more pain, thanks to you."),
+ l("I can walk again!");
+ setarray .msg_first[0], 0, 3, 6;
+ setarray .msg_last[0], 2, 5, 8;
+ .@r = rand(.msg_first[.@q],.msg_last[.@q]);
+ .@msg$ = .messages$[.@r];
+ npctalk3 .@msg$;
+ @ArtisQuests_Urchin_MoonMsgTick = .@tick;
+ }
+ }
+
+ function CheckCrowClaw {
+ if (getq(ArtisQuests_Urchin) != 1)
+ return -1;
+
+ mes "";
+ mesn;
+ if (countitem("CrocClaw") > 0)
+ {
+ delitem "CrocClaw", 1;
+ if (rand(8) == 7) // the lucky 7
+ {
+ mesq l("Yay, it worked! I removed a spike.");
+ ArtisQuests_Urchin_ULeft--;
+ next;
+ if (!ArtisQuests_Urchin_ULeft)
+ {
+ mesq l("It seems I got them all!");
+ next;
+ mesq l("Here is your reward.");
+ setq ArtisQuests_Urchin, 2;
+ getexp 1500, 100;
+ close2;
+ return 1;
+ }
+ else
+ {
+ mesq l("But I still have some spikes left in my foot.");
+ next;
+ return 0;
+ }
+ }
+ else
+ {
+ mesq l("This one is useless! Give me another @@.", getitemlink("CrocClaw"));
+ next;
+ return 0;
+ }
+ }
+ else
+ {
+ mesq l("You don't have any @@, are you mocking me?", getitemlink("CrocClaw"));
+ close2;
+ return 1;
+ }
+ }
+
+ stopnpctimer;
+
+ .@q = getq(ArtisQuests_Urchin);
+ if (.@q < 2)
+ {
+ mesn "Narrator";
+ mes col(l("You see a young elven girl, with a strong sense of pain in her face."), 9);
+ next;
+ }
+ else
+ {
+ mesn;
+ mesq l("I appreciate your help, @@.", strcharinfo(0));
+ goto L_Close;
+ }
+ if (.@q == 1) goto L_QuestStarted;
+
+L_Story:
+ select
+ l("Hi, can I help you somehow?");
+ mes "";
+ mesn;
+ mesq l("That would be great!");
+ next;
+ mesq l("Hi, my name is Moon. This morning I went for a walk on the beach.");
+ next;
+ mesq l("Walking barefoot, feeling the hot sand with my feet, daydreaming... I like such things, you know.");
+ next;
+ mesq l("I didn't notice that a Pikpik was in my way, and when I stepped on it, my foot was full of spikes.");
+ next;
+ mesq l("Luckily the beach is nearby, and somehow I made my way home.");
+ next;
+ mesq l("Please bring me @@s so I can pull out these spikes from my foot.", getitemlink("CrocClaw"));
+ next;
+
+ switch (select(l("Stay here, I will be back as soon as I have some."),
+ l("Maybe next time.")))
+ {
+ case 1:
+ setq ArtisQuests_Urchin, 1;
+ mes "";
+ mesn;
+ mesq l("It really hurts, please hurry!");
+
+ ArtisQuests_Urchin_ULeft = rand(3,5);
+
+ next;
+ goto L_Where;
+ break;
+ case 2:
+ mes "";
+ mesn "Narrator";
+ mes col(l("The girl looks desperate."),9);
+ }
+ goto L_Close;
+
+L_QuestStarted:
+ mesn;
+ mesq l("Do you have @@s for me?", getitemlink("CrocClaw"));
+ next;
+
+ select
+ l("Check out this one."),
+ l("I should put more effort into this."),
+ l("Where can I find some Croc Claws?");
+
+ switch (@menu)
+ {
+ case 1:
+ .@MustRepeat = CheckCrowClaw;
+ if (!.@MustRepeat)
+ goto L_CheckLoop;
+ goto L_Close;
+ case 2:
+ mes "";
+ mesn;
+ mesq l("It really hurts, please hurry!");
+ goto L_Close;
+ case 3:
+ mes "";
+ mesn;
+ goto L_Where;
+ }
+
+L_CheckLoop:
+ while (!.@MustRepeat)
+ {
+ switch (select(l("Here is another one."),
+ l("I must leave to get more.")))
+ {
+ case 1:
+ .@MustRepeat = CheckCrowClaw;
+ break;
+ case 2:
+ goto L_Close;
+ }
+ }
+ goto L_Close;
+
+L_Where:
+ mesq l("You can find some Crocs on the beach, you could look up at the one after the gate, on top of this city.");
+
+ goto L_Close;
+
+L_Close:
+ initnpctimer;
+ close;
+
+OnTimer1000:
+ domovestep;
+
+OnTouch:
+ SayRandomGreeting;
+ end;
+
+OnHour00:
+ if (playerattached())
+ @ArtisQuests_Urchin_MoonMsgTick = 0;
+ end;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 3;
+ initpath "move", 41, 30,
+ "dir", DOWN, 0,
+ "wait", 2, 0,
+ "move", 33, 32,
+ "dir", DOWN, 0,
+ "wait", 10, 0;
+ initialmove;
+ initnpctimer;
+}
diff --git a/npc/001-2-20/_import.txt b/npc/001-2-20/_import.txt
new file mode 100644
index 000000000..5929d2416
--- /dev/null
+++ b/npc/001-2-20/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-2-20: Backroom
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-20/_warps.txt",
+"npc/001-2-20/mapflags.txt",
diff --git a/npc/001-2-20/_warps.txt b/npc/001-2-20/_warps.txt
new file mode 100644
index 000000000..a032fa4d8
--- /dev/null
+++ b/npc/001-2-20/_warps.txt
@@ -0,0 +1,26 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-20: Backroom warps
+001-2-20,33,35,0 warp #001-2-20_33_35 0,0,001-1,107,50
+001-2-20,29,25,0 script #001-2-20_29_25_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-19", 41, 54;
+close;
+
+OnUnTouch:
+ doevent "#001-2-20_29_25::OnUnTouch";
+}
+001-2-20,29,25,0 script #001-2-20_29_25 NPC_ARTIS_DOOR_WOOD,2,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
diff --git a/npc/001-2-20/mapflags.txt b/npc/001-2-20/mapflags.txt
new file mode 100644
index 000000000..499fd5a60
--- /dev/null
+++ b/npc/001-2-20/mapflags.txt
@@ -0,0 +1 @@
+001-2-20 mapflag town
diff --git a/npc/001-2-21/_import.txt b/npc/001-2-21/_import.txt
new file mode 100644
index 000000000..b0f7a5a14
--- /dev/null
+++ b/npc/001-2-21/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-21: First Deck
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-21/_warps.txt",
+"npc/001-2-21/julia.txt",
+"npc/001-2-21/mapflags.txt",
+"npc/001-2-21/note.txt",
diff --git a/npc/001-2-21/_warps.txt b/npc/001-2-21/_warps.txt
new file mode 100644
index 000000000..01f70e01b
--- /dev/null
+++ b/npc/001-2-21/_warps.txt
@@ -0,0 +1,5 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-21: First Deck warps
+001-2-21,19,28,0 warp #001-2-21_19_28 0,0,001-1,193,109
+001-2-21,33,28,0 warp #001-2-21_33_28 0,0,001-2-24,20,27
+001-2-21,31,25,0 warp #001-2-21_31_25 0,0,001-2-22,72,29
diff --git a/npc/001-2-21/julia.txt b/npc/001-2-21/julia.txt
new file mode 100644
index 000000000..008cdb41e
--- /dev/null
+++ b/npc/001-2-21/julia.txt
@@ -0,0 +1,141 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Qwerty Dragon
+// Reid
+// Vasily_Makarov
+// Description:
+// Allows to change language.
+
+001-2-21,27,24,0 script Julia#Artis NPC_JULIA,{
+ mesn;
+ mesq lg("Hello dear!");
+ next;
+ mesq l("What do you want today?");
+ next;
+
+ .@s$ = l("I don't want to change my language, sorry.");
+
+L_Menu:
+ .@enora = getq(ArtisQuests_Enora);
+
+ menu
+ rif(getskilllv(1) < 6, l("Something is wrong with me, I can't smile nor sit.")), L_BasicSkill,
+ rif(.@enora == 0, l("Where should I go?")), L_Enora,
+ lg("I made a mistake, I would like to change my language."), L_ChooseLang,
+ l("Is it possible to go back to Drasil Island?"), L_Island,
+ l("Could you explain to me where I am?"), L_WhereIam,
+ l("What happened to me?"), L_What,
+ l("Can I read the rules again?"), L_Rules,
+ l("Nothing, sorry."), L_Quit;
+
+L_YNMenu:
+ menu
+ l("Yes, I do."), L_Menu,
+ l("No, none."), L_Quit;
+
+L_NoChanges:
+ mes "";
+ mesn;
+ mesq l("No problem, do you have any other questions for me?");
+ next;
+
+ goto L_YNMenu;
+
+L_ChooseLang:
+ mes "";
+ mesn;
+ mesq l("Of course! Tell me which language you speak and I will change the note on the ship board list.");
+ next;
+
+ asklanguage(LANG_IN_SHIP);
+
+ mes "";
+ mesn;
+ mesq l("Ok, done.");
+ next;
+ mesq l("Do you have any other questions for me?");
+ next;
+
+ goto L_Menu;
+
+L_WhereIam:
+ mes "";
+ mesn;
+ mesq l("You're on La Johanne, a merchant ship.");
+ next;
+ mesq l("We arrived this morning at the port of Artis, I already warned the Legion of Aemil concerning your issue.");
+ next;
+ mesq l("Somebody is waiting for you outside!");
+ next;
+ mesq lg("Like the rest of the crew, you are welcome to come and rest here at anytime during your journey on Artis.");
+ next;
+ mesq l("Do you have any other questions for me?");
+ next;
+
+ goto L_YNMenu;
+
+L_What:
+ mes "";
+ mesn;
+ mesq lg("We thought that you could help us understand this, all we know is that we found you cast in the sea, adrift on your raft.");
+ next;
+ mesq lg("You were in bad shape, you should be happy we found you before the sea killed you.");
+ next;
+ mesq l("Oh, and there was this inscription on your raft. It represents the Legion of Aemil, the largest and biggest guild of the whole new world. Does that make you remember anything, anything at all?");
+ next;
+
+ select
+ l("Sorry, but I can't tell you anything about that."),
+ l("Nothing, sorry.");
+
+ goto L_NoChanges;
+
+L_Rules:
+ mes "";
+ mesn;
+ mesq l("Of course, they are on the left wall. Go have a look at them.");
+ next;
+ mesq l("Do you have any other questions for me?");
+ next;
+
+ goto L_YNMenu;
+
+L_BasicSkill:
+ mes "";
+ mesn;
+ mesq l("Let me check into it...");
+ next;
+ adddefaultskills;
+ mesq l("Here you go, everything is fixed.");
+ emotion E_HAPPY;
+ next;
+ mesq l("Do you have any other questions for me?");
+ next;
+
+ goto L_YNMenu;
+
+L_Enora:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Enora, from the Legion of Aemil, has been warned that you were aboard."),
+ l("She is waiting for you on the dock."),
+ l("Do you have any other questions for me?");
+
+ goto L_YNMenu;
+
+L_Quit:
+ goodbye;
+
+L_Island:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Of course, as a fully-fledged crew member you can decide of the destination of La Johanne directly with Nard.");
+ l("Do you have any other questions for me?");
+ emotion E_HAPPY;
+
+ goto L_YNMenu;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 10;
+ end;
+}
diff --git a/npc/001-2-21/mapflags.txt b/npc/001-2-21/mapflags.txt
new file mode 100644
index 000000000..a3f0260b3
--- /dev/null
+++ b/npc/001-2-21/mapflags.txt
@@ -0,0 +1 @@
+001-2-21 mapflag town
diff --git a/npc/001-2-21/note.txt b/npc/001-2-21/note.txt
new file mode 100644
index 000000000..cd1764ed4
--- /dev/null
+++ b/npc/001-2-21/note.txt
@@ -0,0 +1,27 @@
+// Evol scripts.
+// Authors:
+// gumi
+// Qwerty Dragon
+// Reid
+// WildX
+// Description:
+// A small note presenting the 6 main rules of Evol Online.
+
+001-2-21,29,25,0 script Note#Artis NPC_PAPER_NOTE,{
+ narrator S_LAST_NEXT,
+ l("There is a paper with some rules written on it.");
+
+ GameRules 8 | 4;
+
+ narrator S_NO_NPC_NAME,
+ l("Following these lines are some other writings on this paper."),
+ l("Do not give the password of your room to anybody! Keep it secret and try not to use the same one in any other room in the future. - Julia"),
+ l("Does anyone know a good place to hang out in Esperia? - M. Arpan"),
+ l("Other things are written but are not legible anymore.");
+
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-22/_import.txt b/npc/001-2-22/_import.txt
new file mode 100644
index 000000000..96490c742
--- /dev/null
+++ b/npc/001-2-22/_import.txt
@@ -0,0 +1,13 @@
+// Map 001-2-22: Second Deck
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-22/_mobs.txt",
+"npc/001-2-22/_savepoints.txt",
+"npc/001-2-22/_warps.txt",
+"npc/001-2-22/alige.txt",
+"npc/001-2-22/chefgado.txt",
+"npc/001-2-22/chest.txt",
+"npc/001-2-22/hammock.txt",
+"npc/001-2-22/knife.txt",
+"npc/001-2-22/mapflags.txt",
+"npc/001-2-22/note.txt",
+"npc/001-2-22/peter.txt",
diff --git a/npc/001-2-22/_mobs.txt b/npc/001-2-22/_mobs.txt
new file mode 100644
index 000000000..a2164e451
--- /dev/null
+++ b/npc/001-2-22/_mobs.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-22: Second Deck mobs
+001-2-22,52,32,21,9 monster Piou 1002,3,30000,20000
diff --git a/npc/001-2-22/_savepoints.txt b/npc/001-2-22/_savepoints.txt
new file mode 100644
index 000000000..a0bd9f89e
--- /dev/null
+++ b/npc/001-2-22/_savepoints.txt
@@ -0,0 +1,47 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-22: Second Deck saves
+001-2-22,40,37,0 script #save_001-2-22_40_37 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-22,46,37,0 script #save_001-2-22_46_37 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-22,55,40,0 script #save_001-2-22_55_40 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-22,50,38,0 script #save_001-2-22_50_38 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-22,53,38,0 script #save_001-2-22_53_38 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-2-22/_warps.txt b/npc/001-2-22/_warps.txt
new file mode 100644
index 000000000..8fcdb2c3c
--- /dev/null
+++ b/npc/001-2-22/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-22: Second Deck warps
+001-2-22,72,30,0 warp #001-2-22_72_30 0,0,001-2-21,31,26
diff --git a/npc/001-2-22/alige.txt b/npc/001-2-22/alige.txt
new file mode 100644
index 000000000..70e6058e4
--- /dev/null
+++ b/npc/001-2-22/alige.txt
@@ -0,0 +1,324 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Alige
+// Qwerty Dragon
+// Reid
+// Vasily_Makarov
+// Description:
+// Hidden in a ship's hole.
+// 2 bits array:
+// ShipQuests
+// Variable:
+// ShipQuests_Alige
+// Values:
+// 0 Never talk.
+// 1 First talk.
+// 2 Accept the task.
+// 3 Bring first food.
+
+001-2-22,43,32,0 script AligeTrigger#Artis NPC_HIDDEN,1,1,{
+
+OnTouch:
+ if (getareausers() <= 1)
+ {
+ setnpcdir "Alige#Artis", 2;
+ stopnpctimer;
+ initnpctimer;
+ }
+
+ if (getq(ShipQuests_Alige) > 0) close;
+ doevent "Alige#Artis::OnFirstEncounter";
+
+ close;
+
+OnUnTouch:
+ if (getareausers() == 0)
+ {
+ setnpcdir "Alige#Artis", 4;
+ stopnpctimer;
+ initnpctimer;
+ }
+ close;
+
+OnTimer190:
+ stopnpctimer;
+
+ if (getnpcdir("Alige#Artis") == 2) setnpcdir "Alige#Artis", 6;
+ if (getnpcdir("Alige#Artis") == 4) setnpcdir "Alige#Artis", 8;
+
+ end;
+}
+
+001-2-22,43,31,0 script Alige#Artis NPC_ALIGE,{
+ .@q = getq(ShipQuests_Alige);
+ if (.@q > 1) goto L_AskForFood;
+
+ goto OnFirstEncounter;
+
+OnFirstEncounter:
+ setq ShipQuests_Alige, 1;
+
+ setcamnpc;
+ mesn "Hidden Person";
+ mesq l("Hey, psst! You're not a sailor, right?");
+ next;
+ restorecam;
+
+ menu
+ lg("I am, who are you?"), -,
+ lg("Indeed, I am not."), L_NeedHelp;
+
+ mes "";
+ mesn "Narrator";
+ mes col(l("The stowaway doesn't answer."), 9);
+
+ close;
+
+L_NeedHelp:
+ setcamnpc;
+ mes "";
+ mesn "Hidden Person";
+ mesq l("Good, good... Hey, could you help me please? I beg you, please, pleeeease...");
+ next;
+ restorecam;
+
+ menu
+ l("Why not, but who are you, and what kind of help do you need?"), L_CanHelp;
+ l("Sorry but I have no time for this."), -;
+
+ closedialog;
+ close;
+
+L_CanHelp:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("My name is Alige, I've been hiding here for weeks. All I have to eat are these berries... berries... berries...");
+ next;
+ mesq l("I'm losing my mind here, I need something else to eat!");
+ next;
+ mesq l("Could you please bring me something which isn't a berry, and I'm not big on vegetables either. I need proteins!");
+ next;
+ restorecam;
+
+ menu
+ l("Sure, but what will you give me in exchange?"), L_AboutReward,
+ l("Why don't you come out?"), -;
+
+L_ExplainHiding:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("No, I can't. I won't! All I wanted was to travel across the seas for fun, growl... sniff. And in this hole in the floor, as you can see, I have lots of fun.");
+ next;
+ mesq l("Oh... um... actually... all I wanted was to get to Artis. Err... but I didn't, uhm... have enough money to pay for the ferry!");
+ next;
+ mesq l("Please don't tell people you saw me. I don't want to be decapitated or get thrown into the sea as food for sharks, or get my hair mussed!");
+ next;
+ restorecam;
+
+ if (getq(ShipQuests_Alige) == 2) goto L_SoAskForFood;
+ goto L_Accept;
+
+L_AboutReward:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("I'll share my berries with you if you help me.");
+ next;
+ restorecam;
+
+L_Accept:
+ menu
+ l("Understood, I will help you."), L_FirstAccepted,
+ l("We arrived in Artis today."), L_Artis,
+ l("I think I should report you to the crew members."), -;
+
+ setcamnpc;
+ mesq lg("Growl, sniff, grr! You'd better not tell anyone you saw me!");
+
+ close;
+
+L_Artis:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("Of course, so why do I still see open sea from the porthole?");
+ next;
+ mesq l("I wonder who is in delarium now...");
+ next;
+ mesq l("But hey, back to me. Remember my mentioning that I'm hun...grrr...eee!");
+ next;
+ restorecam;
+
+ if (.@q == 2) goto L_SoAskForFood;
+ goto L_Accept;
+
+L_FirstAccepted:
+ if (getq(ShipQuests_Alige) >= 2) goto L_Accepted;
+ setq ShipQuests_Alige, 2;
+
+ goto L_Accepted;
+
+L_Accepted:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq lg("Great, what food do you have for me today?");
+ next;
+ restorecam;
+
+L_GiveFood:
+ mes "";
+ menuint
+ rif(countitem(Acorn), l(getitemname(Acorn))), 0,
+ rif(countitem(Bread), l(getitemname(Bread))), 502,
+ rif(countitem(Fungus), l(getitemname(Fungus))), 503,
+ rif(countitem(Cheese), l(getitemname(Cheese))), 504,
+ rif(countitem(PiouLegs), l(getitemname(PiouLegs))), 505,
+ rif(countitem(LettuceLeaf), l(getitemname(LettuceLeaf))), 0,
+ rif(countitem(Piberries), l(getitemname(Piberries))), 2,
+ rif(countitem(SeaDrops), l(getitemname(SeaDrops))), 1,
+ rif(countitem(Aquada), l(getitemname(Aquada))), 509,
+ rif(countitem(PinkBlobime), l(getitemname(PinkBlobime))), 1,
+ rif(countitem(HalfCroconut), l(getitemname(HalfCroconut))), 512,
+ rif(countitem(Croconut), l(getitemname(Croconut))), 0,
+ rif(countitem(Plushroom), l(getitemname(Plushroom))), 515,
+ rif(countitem(PumpkinSeeds), l(getitemname(PumpkinSeeds))), 1,
+ rif(countitem(UrchinMeat), l(getitemname(UrchinMeat))), 1,
+ rif(countitem(EasterEgg), l(getitemname(EasterEgg))), 1,
+ rif(countitem(PumpkishJuice), l(getitemname(PumpkishJuice))), 527,
+ rif(countitem(Manana), l(getitemname(Manana))), 528,
+ rif(countitem(Curshroom), l(getitemname(Curshroom))), 529,
+ rif(countitem(Carrot), l(getitemname(Carrot))), 530,
+ rif(countitem(RedPlushWine), l(getitemname(RedPlushWine))), 3,
+ l("I don't have anything good for you today."), -1;
+
+ .@id = @menuret;
+ if (.@id == -1) goto L_Quit; // Quit message.
+ if (.@id == 0) goto L_NoReward; // In case of wrong food.
+ if (.@id == 1) goto L_Poison; // In case of poisoned food.
+ if (.@id == 2) goto L_NoMore; // In case of Piberries.
+ if (.@id == 3) goto L_Drunk; // In case of Alcohol.
+ if (countitem(.@id) == 0) goto L_Quit;
+// if (.@id == item's ID) then food is correct.
+// Do not put any other number than -1, 0, 1, 2 or the item's ID, that'll avoid confusion.
+
+ inventoryplace Piberries, 3;
+ delitem .@id, 1;
+
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("Thank you so much! Here, have some of my berries.");
+
+ setq ShipQuests_Alige, 3;
+ getitem Piberries, rand(1, 3);
+ next;
+
+ goto L_ReturnMenu;
+
+L_NoReward:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("You don't expect me to eat that, do you? Give me something else!");
+ next;
+ restorecam;
+
+ goto L_GiveFood;
+
+L_Drunk:
+ setcamnpc;
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I asked for food but... *hips* Ah, that'll do nicely!");
+ restorecam;
+
+ goto L_GiveFood;
+
+L_ReturnMenu:
+ setcamnpc;
+ mesq l("Do you have anything else for me?");
+ next;
+ restorecam;
+
+ goto L_GiveFood;
+
+L_NoMore:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("Grr, don't give me more berries! I don't want them, stupid berries, stupid... Stupid... Stupid!");
+ next;
+
+ goto L_ReturnMenu;
+
+L_Poison:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("Don't try to poison me! I know what that does!");
+ next;
+ restorecam;
+ goto L_ReturnMenu;
+
+L_SoAskForFood:
+ setcamnpc;
+ mesn;
+ mesq l("So, do you have anything for me today?");
+ next;
+ restorecam;
+ goto L_IntroMenu;
+
+L_AskForFood:
+ setcamnpc;
+ mesn;
+ mesq l("Do you have anything for me today?");
+ next;
+ restorecam;
+
+L_IntroMenu:
+ menu
+ l("Yes."), L_GiveFood,
+ l("Where can I find some food?"), L_FindFood,
+ l("Why are you hiding?") + " " + l("Why don't you come out?"), L_ExplainHiding,
+ l("We arrived in Artis today."), L_Artis,
+ l("I think I should report you to the crew members."), -;
+
+ setcamnpc;
+ mesq lg("Growl, sniff, grr! You'd better not tell anyone you saw me!");
+
+ close;
+
+L_FindFood:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("There are some flying yellow plushes around you. They're called pious. Getting a roasted leg of one of them would be perfect.");
+ next;
+ mesq l("I'd like to catch one of them, but they fly away when I try.");
+ next;
+ mesq l("Walking around a bit, it'll be easy for you to catch one, I bet. Impale one of them for me please.");
+ next;
+ restorecam;
+ mesn "Narrator";
+ mes col(l("You can attack a monster by clicking on it, or from your keyboard you can press the 'A' key to select the monster followed by 'Ctrl' to attack it."), 9);
+ next;
+ mes col(l("Once the monster is dead, click on the dropped items to add them to your inventory. You can also use the 'Z' key to claim the drops."), 9);
+
+ close;
+
+L_Quit:
+ setcamnpc;
+ mes "";
+ mesn;
+ mesq l("Too bad... Come back when you'll have some nice food for me. Growl... grumble... grumble.");
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-22/chefgado.txt b/npc/001-2-22/chefgado.txt
new file mode 100644
index 000000000..329d8567d
--- /dev/null
+++ b/npc/001-2-22/chefgado.txt
@@ -0,0 +1,22 @@
+// Evol scripts.
+// Authors:
+// Hal9000
+// Qwerty Dragon
+// Reid
+// Description:
+// La Johanne Chef.
+
+001-2-22,27,28,0 script Chef Gado#Artis NPC_CHEF_GADO,{
+
+ .@r = rand(3);
+ if (.@r == 0) npctalk3 l("What are you doing in my kitchen?! Get out, it's not a place for kids!");
+ if (.@r == 1) npctalk3 l("Where is the damn salt?! Give me the salt, I know you have it!");
+ if (.@r == 2) npctalk3 l("Are you going to stand here all day long? Do the dishes or go away.");
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-22/chest.txt b/npc/001-2-22/chest.txt
new file mode 100644
index 000000000..010f5a799
--- /dev/null
+++ b/npc/001-2-22/chest.txt
@@ -0,0 +1,49 @@
+// Evol scripts.
+// Authors:
+// 4144
+// gumi
+// Reid
+// Description:
+// A box with clothes for new players.
+
+001-2-22,51,37,0 script Chest#Artis NPC_CHEST_BIG,2,4,{
+
+ if (.busy == false)
+ {
+ specialeffect(.dir == 0 ? 24 : 25, AREA, getnpcid(0)); // closed ? opening : closing
+ .dir = .dir == 0 ? 2 : 6; // closed ? opening : closing
+ .busy = true; // lock until available again
+ initnpctimer;
+ }
+ end;
+
+OnTimer220:
+ .dir = .dir == 6 ? 0 : 4; // closing ? closed : open
+ end;
+
+OnTimer500:
+ .busy = false; // unlock
+
+ if (.dir == 0)
+ {
+ stopnpctimer; // stop here if the chest is closed
+ }
+ end;
+
+OnUnTouch:
+ if (getareausers(.x - 2, .y - 4, .x + 2, .y + 6) > 0 || .dir == 0)
+ {
+ end;
+ }
+OnTimer30000:
+ .busy = true;
+ .dir = 6; // closing
+ specialeffect(25, AREA, getnpcid(0)); // closing
+ setnpctimer 0;
+OnTouch:
+ end;
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-22/hammock.txt b/npc/001-2-22/hammock.txt
new file mode 100644
index 000000000..f6f700442
--- /dev/null
+++ b/npc/001-2-22/hammock.txt
@@ -0,0 +1,137 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Animated hammock at the mid level of the ship.
+
+001-2-22,32,27,0 script #hammockArtis1 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,32,25,0 script #hammockArtis2 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,37,25,0 script #hammockArtis3 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,37,27,0 script #hammockArtis4 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,37,29,0 script #hammockArtis5 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,37,34,0 script #hammockArtis6 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,37,36,0 script #hammockArtis7 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,37,38,0 script #hammockArtis8 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,37,40,0 script #hammockArtis9 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,32,38,0 script #hammockArtis10 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-22,32,40,0 script #hammockArtis11 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchLeft;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
diff --git a/npc/001-2-22/knife.txt b/npc/001-2-22/knife.txt
new file mode 100644
index 000000000..7502b1631
--- /dev/null
+++ b/npc/001-2-22/knife.txt
@@ -0,0 +1,47 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Qwerty Dragon
+// Description:
+// Knife on the table.
+// Variable:
+// ShipQuests_Knife
+// Values:
+// 0 Default, not taken.
+// 1 Knife taken.
+
+000-2-1,50,24,0 script #Artisknife NPC_KNIVES,{
+ .@q = getq(ShipQuests_Knife);
+ if (.@q) close;
+
+ mesn "Narrator";
+ mes col(l("There are some knives on the table. Would you like to take one?"), 9);
+ next;
+
+ menu
+ l("Yes."), L_Give,
+ l("No."), -;
+
+ closedialog;
+ close;
+
+L_Give:
+ mes "";
+ inventoryplace Knife, 1;
+
+ setq ShipQuests_Knife, 1;
+ getitem Knife, 1;
+
+ mesn "Narrator";
+ mes col(l("To open your inventory, use the F3 key or use your mouse to select it in the above menu in your client."), 9);
+ next;
+ mes col(l("When your inventory is open, you can equip an item by selecting it and clicking 'Equip'. You can do the same to unequip an item by clicking on 'Unequip'."), 9);
+ next;
+ mes col(l("Items have different effects. Some will heal you, some can be used as weapons or armor, and some can be sold for gold."), 9);
+
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-22/mapflags.txt b/npc/001-2-22/mapflags.txt
new file mode 100644
index 000000000..fdb4e3e22
--- /dev/null
+++ b/npc/001-2-22/mapflags.txt
@@ -0,0 +1 @@
+001-2-22 mapflag town
diff --git a/npc/001-2-22/note.txt b/npc/001-2-22/note.txt
new file mode 100644
index 000000000..b2560503e
--- /dev/null
+++ b/npc/001-2-22/note.txt
@@ -0,0 +1,33 @@
+// Evol scripts.
+// Author:
+// Vasily_Makarov
+// Description:
+//
+
+001-2-22,31,31,0 script Note#001-2-22 NPC_DAN_NOTE,{
+ mesn;
+ mesq l("This note was left by somebody.");
+ next;
+ mesq l("What do you want to do with it?");
+
+ menu
+ l("Read it."), L_Content,
+ l("Leave it."), -;
+ close;
+
+L_Content:
+ mesn;
+ mes "\"" + l("Dear sister,");
+ mes l("In a couple of days, we will finally reach Artis.");
+ next;
+
+ mes l("I will send you this letter as soon as I arrive.");
+ mes l("Don't worry sister, I didn't forget you.");
+ next;
+
+ mes l("I would like to come back home when the days are better.");
+ mes l("And when we have enough money for ourselves without needing anybody else.");
+
+ mes l("Sincerely yours, Dan.") + "\"";
+ close;
+}
diff --git a/npc/001-2-22/peter.txt b/npc/001-2-22/peter.txt
new file mode 100644
index 000000000..0365392af
--- /dev/null
+++ b/npc/001-2-22/peter.txt
@@ -0,0 +1,335 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Ablu
+// Alastrim
+// Qwerty Dragon
+// Reid
+// Vasily_Makarov
+// Description:
+// Rat hunter.
+// 4+2 bits array:
+// ShipQuests
+// Variable:
+// ShipQuests_Peter
+// Values:
+// 0 Doesn't know the quest.
+// 1 Task given.
+// 2 Task given and reward expected.
+// 3 Task completed without reward.
+// 4 Asked for reward after completion of the task.
+// 5 Task done and reward given.
+// 6 Did not start the quest.
+// Others:
+// .@peter = Peter#001-2-22 variable.
+// "001-2-23" - map with mobs.
+// "$@ARTIS_RAT1_HELPER$" - Name of the participant.
+// "$@ARTIS_RAT1_DEATHS - Number of deaths when the participant starts the fight.
+// "$@ARTIS_RAT1_CONTROL" - Explanation of each index of the array.
+// "$@ARTIS_RAT1_OLD_HELPER$" - Name of the participant.
+// "$@ARTIS_RAT1_COUNTDOWN" - Seconds since the epoch of when the player done the quest.
+// [1] = Shows status of ratto number 1 (1 is dead and 0 is alive).
+// [2] = Shows status of ratto number 2 (1 is dead and 0 is alive).
+// [3] = Shows status of ratto number 3 (1 is dead and 0 is alive).
+// [4] = Shows status of ratto number 4 (1 is dead and 0 is alive).
+// [5] = Shows how many seconds passed since ratto number 1 died.
+// [6] = Shows how many seconds passed since ratto number 2 died.
+// [7] = Shows how many seconds passed since ratto number 3 died.
+// [8] = Shows how many seconds passed since ratto number 4 died.
+// [9] = Shows how many seconds passed since the player started the quest.
+// [10] = Shows how many seconds passed since the player done the quest.
+
+001-2-22,72,34,0 script AreaNPC#001-2-22 NPC_HIDDEN,0,1,{
+
+OnTouch:
+ if (BaseLevel < 5) goto L_Stop;
+ if ($@ARTIS_RAT1_COUNTDOWN == 0) goto L_NoCountDown;
+ if ((gettimetick(2) - $@ARTIS_RAT1_COUNTDOWN) < 10) goto L_NoGoodTick;
+ if (($@ARTIS_RAT1_OLD_HELPER$ == strcharinfo(0)) && ((gettimetick(2) - $@ARTIS_RAT1_COUNTDOWN) < 60)) goto L_NoGoodTick;
+ $@ARTIS_RAT1_COUNTDOWN = 0;
+
+L_NoCountDown:
+ if ($@ARTIS_RAT1_HELPER$ != "") goto L_Occupied;
+ .@peter = getq(ShipQuests_Peter);
+ if (.@peter < 1 || .@peter > 5) goto L_Task;
+ if (.@peter == 1 || .@peter == 2) goto L_Rfail;
+ if (.@peter == 3 || .@peter == 4) goto L_Rwin;
+ if (.@peter > 5) goto L_SecondTime;
+ doevent "Peter#001-2-22::OnReturnWin";
+ close;
+
+L_Stop:
+ doevent "Peter#001-2-22::OnStop";
+
+ close;
+
+L_Occupied:
+ doevent "Peter#001-2-22::OnDontneedHelp";
+
+ close;
+
+L_Task:
+ doevent "Peter#001-2-22::OnGiveTask";
+
+ close;
+
+L_Rfail:
+ doevent "Peter#001-2-22::OnReturnFail";
+
+ close;
+
+L_Rwin:
+ doevent "Peter#001-2-22::OnReturnWin";
+
+ close;
+
+L_NoGoodTick:
+ doevent "Peter#001-2-22::OnNoGoodTick";
+
+ close;
+}
+
+001-2-22,70,35,0 script Peter#001-2-22 NPC_RATTO_SAILOR,{
+ if (BaseLevel < 5) goto OnTooWeak;
+ if ($@ARTIS_RAT1_COUNTDOWN == 0) goto L_NoCountDown;
+ if ((gettimetick(2) - $@ARTIS_RAT1_COUNTDOWN) < 10) goto OnNoGoodTick;
+ if (($@ARTIS_RAT1_OLD_HELPER$ == strcharinfo(0)) && ((gettimetick(2) - $@ARTIS_RAT1_COUNTDOWN) < 60)) goto OnNoGoodTick;
+ $@ARTIS_RAT1_COUNTDOWN = 0;
+
+L_NoCountDown:
+ .@peter = getq(ShipQuests_Peter);
+ if (.@peter == 1 || .@peter == 2) goto OnReturnFail;
+ if (.@peter == 3 || .@peter == 4 || .@peter == 5) goto OnReturnWin;
+
+OnGiveTask:
+ setq ShipQuests_Peter, 6;
+ .@peter = getq(ShipQuests_Peter);
+ mesn;
+ mesq lg("Hey, girl!", "Hey, man!");
+ next;
+ mesq l("I need somebody who can rid the hold of the ship of these rattos. Can you help me?");
+ next;
+
+ menu
+ l("Yeah, but what reward will I get?"), L_BonusTask,
+ l("Why not, I need to train anyway."), L_Task,
+ l("No, they are way too dangerous for me!"), -;
+
+ mes "";
+ mesn;
+ mesq l("Hehe, hehe. Well, come back if you change your mind.");
+
+ goto L_Quit;
+
+OnTooWeak:
+ mesn;
+ mesq lg("I need someone to help me clean the edge of the ship, but you aren't strong enough for now.");
+
+ goto L_Quit;
+
+OnStop:
+ warp "001-2-22", 72, 36;
+
+ mesn;
+ mesq l("You can't go there!");
+
+ close;
+
+OnReturnFail:
+ mesn;
+ mesq l("I see it's not so easy to get rid of these rattos. Do you want to try again?");
+ next;
+
+ menu
+ l("Yeah, but I would like to make sure I get a reward."), L_BonusTask,
+ l("Why not, I need to train anyway."), L_Task,
+ l("No, they are way too dangerous for me!"), -;
+
+ mes "";
+ mesn;
+ mesq l("Hehe, hehe. Well, come back if you change your mind.");
+
+ goto L_Quit;
+
+OnReturnWin:
+ .@peter = getq(ShipQuests_Peter);
+ mesn;
+ mesq l("Thanks again for helping me. Drats these rattos for infesting our fair vessal! They are a permanent problem so I will always need your help to exterminate them in order to keep their number under control. Your help is very welcome indeed. Unfortunately, I can give you a reward only for the first extermination.");
+ next;
+
+ if (.@peter == 3 || .@peter == 4)
+ menu
+ l("Did you say reward? I want it!"), L_BonusTask,
+ l("I am not worried about rewards. I just want to help."), L_Task,
+ l("Sorry, I am not in the mood for another fight with these rattos."), -;
+
+ if (.@peter == 5)
+ menu
+ l("No problem, I can help you anyway."), L_Task,
+ l("Sorry, I am not in the mood for another fight with these rattos."), -;
+
+ mes "";
+ mesn;
+ mesq l("Hehe, hehe. Well, come back if you change your mind.");
+
+ close;
+
+L_BonusTask:
+ mes "";
+ mesn;
+ mesq l("What if I give you 1000 Esperin for that job, is it ok?");
+ next;
+
+ menu
+ lg("Okay, I'm ready to work!"), -,
+ l("What? This reward is too small!"), L_Quit;
+
+ .@peter = getq(ShipQuests_Peter);
+ if ($@ARTIS_RAT1_HELPER$ != "") goto OnDontneedHelp;
+ if (.@peter == 6) setq ShipQuests_Peter, 2;
+ if (.@peter == 3) setq ShipQuests_Peter, 4;
+ .@peter = getq(ShipQuests_Peter);
+ goto L_Start;
+
+L_Task:
+ .@peter = getq(ShipQuests_Peter);
+ if ($@ARTIS_RAT1_HELPER$ != "") goto OnDontneedHelp;
+ if (.@peter == 6) setq ShipQuests_Peter, 1;
+ .@peter = getq(ShipQuests_Peter);
+
+L_Start:
+ mes "";
+ mesn;
+ mesq l("Okay, you can start!");
+
+OnStartOutside:
+ if ($@ARTIS_RAT1_HELPER$ != "") goto OnDontneedHelp;
+ $@ARTIS_RAT1_HELPER$ = strcharinfo(0);
+ $@ARTIS_RAT1_DEATHS = PC_DIE_COUNTER;
+ initnpctimer;
+ warp "001-2-23", 48, 28;
+ doevent "RattosControl#001-2-23::OnSpawn";
+
+ goto L_Quit;
+
+OnTimer2000:
+ if (attachrid(getcharid(3, $@ARTIS_RAT1_HELPER$)) == 0) goto L_Logoff;
+ $@ARTIS_RAT1_CONTROL[9] = $@ARTIS_RAT1_CONTROL[9] + 2;
+ if ($@ARTIS_RAT1_CONTROL[9] > 100) goto L_Timeout;
+ if (PC_DIE_COUNTER > $@ARTIS_RAT1_DEATHS) goto L_Dead;
+ if ($@ARTIS_RAT1_CONTROL[1] && $@ARTIS_RAT1_CONTROL[2] && $@ARTIS_RAT1_CONTROL[3] && $@ARTIS_RAT1_CONTROL[4]) goto L_Done;
+ if (getmapusers("001-2-23") == 0) goto L_CleaningEnd;
+ goto L_CheckRattos;
+
+ end;
+
+L_CheckRattos:
+ if ($@ARTIS_RAT1_CONTROL[1]) $@ARTIS_RAT1_CONTROL[5] = $@ARTIS_RAT1_CONTROL[5] + 2;
+ if ($@ARTIS_RAT1_CONTROL[2]) $@ARTIS_RAT1_CONTROL[6] = $@ARTIS_RAT1_CONTROL[6] + 2;
+ if ($@ARTIS_RAT1_CONTROL[3]) $@ARTIS_RAT1_CONTROL[7] = $@ARTIS_RAT1_CONTROL[7] + 2;
+ if ($@ARTIS_RAT1_CONTROL[4]) $@ARTIS_RAT1_CONTROL[8] = $@ARTIS_RAT1_CONTROL[8] + 2;
+ if ($@ARTIS_RAT1_CONTROL[5] > 45) doevent "RattosControl#001-2-23::OnRatto1Respawn";
+ if ($@ARTIS_RAT1_CONTROL[6] > 45) doevent "RattosControl#001-2-23::OnRatto2Respawn";
+ if ($@ARTIS_RAT1_CONTROL[7] > 45) doevent "RattosControl#001-2-23::OnRatto3Respawn";
+ if ($@ARTIS_RAT1_CONTROL[8] > 45) doevent "RattosControl#001-2-23::OnRatto4Respawn";
+
+L_NotYet:
+ setnpctimer 0;
+
+ end;
+
+OnDontneedHelp:
+ mesn;
+ mesq l("I don't need your help right now, come back later.");
+ next;
+ mesq l("@@ is helping me.", $@ARTIS_RAT1_HELPER$);
+
+ goto L_Quit;
+
+L_Timeout:
+ mesn;
+ mesq l("Hey! Be careful. You can't stay in this basement for so long, you're going to get sick. Come outside and take a break, maybe you can try again later.");
+ warp "001-2-22", 72, 36;
+
+ goto L_CleaningClose;
+
+L_Logoff:
+ goto L_CleaningEnd;
+
+L_Dead:
+// Warps the dead body outside, so it does not interfere with the getmapusers check.
+ if (getmapusers("001-2-23") > 0) warp "001-2-22", 72, 36;
+
+ goto L_CleaningEnd;
+
+L_Done:
+ $@ARTIS_RAT1_CONTROL[10] = $@ARTIS_RAT1_CONTROL[10] + 2;
+ if($@ARTIS_RAT1_CONTROL[10] < 5) goto L_NotYet;
+ .@peter = getq(ShipQuests_Peter);
+ if (.@peter == 2 || .@peter == 4) goto L_Reward;
+ warp "001-2-22", 72, 36;
+
+ goto L_Thanks;
+
+L_CleaningEnd:
+ stopnpctimer;
+ $@ARTIS_RAT1_HELPER$ = "";
+ $@ARTIS_RAT1_DEATHS = 0;
+ cleararray $@ARTIS_RAT1_CONTROL, 0, 11;
+ killmonster "001-2-23", "RattosControl#001-2-23::OnRatto1Death";
+ killmonster "001-2-23", "RattosControl#001-2-23::OnRatto2Death";
+ killmonster "001-2-23", "RattosControl#001-2-23::OnRatto3Death";
+ killmonster "001-2-23", "RattosControl#001-2-23::OnRatto4Death";
+
+ end;
+
+L_CleaningClose:
+ stopnpctimer;
+ $@ARTIS_RAT1_OLD_HELPER$ = $@ARTIS_RAT1_HELPER$;
+ $@ARTIS_RAT1_HELPER$ = "";
+ $@ARTIS_RAT1_DEATHS = 0;
+ cleararray $@ARTIS_RAT1_CONTROL, 0, 11;
+ killmonster "001-2-23", "RattosControl#001-2-23::OnRatto1Death";
+ killmonster "001-2-23", "RattosControl#001-2-23::OnRatto2Death";
+ killmonster "001-2-23", "RattosControl#001-2-23::OnRatto3Death";
+ killmonster "001-2-23", "RattosControl#001-2-23::OnRatto4Death";
+ $@ARTIS_RAT1_COUNTDOWN = gettimetick(2);
+
+ close;
+
+L_Reward:
+ warp "001-2-22", 72, 36;
+ setq ShipQuests_Peter, 5;
+ .@peter = getq(ShipQuests_Peter);
+ mesn;
+ mesq l("Good job!") + " " + l("Here's your reward!");
+ getexp 100, 0;
+ Zeny = Zeny + 1000;
+ message strcharinfo(0), l("You receive @@ E!", 1000);
+
+ goto L_CleaningClose;
+
+L_Thanks:
+ mesn;
+ mesq l("Thanks for helping me!");
+ .@peter = getq(ShipQuests_Peter);
+ if (.@peter == 1) setq ShipQuests_Peter, 3;
+ .@peter = getq(ShipQuests_Peter);
+
+ goto L_CleaningClose;
+
+L_Quit:
+ .@peter = 0;
+
+ close;
+
+OnNoGoodTick:
+ mesn;
+ mesq l("I don't need your help right now, come back later.");
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
diff --git a/npc/001-2-23/_import.txt b/npc/001-2-23/_import.txt
new file mode 100644
index 000000000..22778b22f
--- /dev/null
+++ b/npc/001-2-23/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-23: Hold
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-23/_warps.txt",
+"npc/001-2-23/doors.txt",
+"npc/001-2-23/mapflags.txt",
+"npc/001-2-23/ratto.txt",
diff --git a/npc/001-2-23/_warps.txt b/npc/001-2-23/_warps.txt
new file mode 100644
index 000000000..d9434efb5
--- /dev/null
+++ b/npc/001-2-23/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-23: Hold warps
+001-2-23,48,29,0 warp #001-2-23_48_29 0,0,001-2-22,72,35
diff --git a/npc/001-2-23/doors.txt b/npc/001-2-23/doors.txt
new file mode 100644
index 000000000..bb192082f
--- /dev/null
+++ b/npc/001-2-23/doors.txt
@@ -0,0 +1,69 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Alastrim
+// Reid
+// Description:
+// Doors NPCs.
+
+001-2-23,48,29,0 script DoorUpwards#001-2-23 NPC_HIDDEN,0,0,{
+
+OnTouch:
+ if (mobcount("001-2-23","all") > 0) goto L_Warn;
+
+ goto L_Warp;
+
+L_Warn:
+ .@q = getq(ShipQuests_Peter);
+ if (.@q == 5) goto L_Warp;
+
+ mesn "Narrator";
+ mes col(l("There are still some rattos left! Do you want to abort the quest?"), 9);
+ next;
+
+ menu
+ l("Yes."), L_Warp,
+ l("No."), -;
+
+ warp "001-2-23", 48, 28;
+ closedialog;
+ close;
+
+L_Warp:
+ warp "001-2-22", 72, 36;
+ closedialog;
+ close;
+}
+
+001-2-23,24,31,0 script LeftDoor#001-2-23 NPC_HIDDEN,0,0,{
+
+OnTouch:
+ mesn "Narrator";
+ mes col(l("It seems that you need a key to open this door."), 9);
+ next;
+ mes col(l("What do you want to do?"), 9);
+ next;
+
+ menu
+ rif(countitem(718) > 0, l("Use the key.")), L_Warp,
+ l("Break the door."), L_Break,
+ l("Go away."), -;
+
+ closedialog;
+ close;
+
+L_Break:
+
+ mes "";
+ mesn "Narrator";
+ mes col(l("You hear a loud scream. It must be the creaking of the wooden door..."), 9);
+
+ close;
+
+L_Warp:
+ mes "";
+ mesn "Narrator";
+ mes col(l("Wait, it seems someone is blocking the door from the other side!"), 9);
+
+ close;
+}
diff --git a/npc/001-2-23/mapflags.txt b/npc/001-2-23/mapflags.txt
new file mode 100644
index 000000000..c8d2d7e7c
--- /dev/null
+++ b/npc/001-2-23/mapflags.txt
@@ -0,0 +1 @@
+001-2-23 mapflag nosave 001-2-22,50,38
diff --git a/npc/001-2-23/ratto.txt b/npc/001-2-23/ratto.txt
new file mode 100644
index 000000000..91a822d3c
--- /dev/null
+++ b/npc/001-2-23/ratto.txt
@@ -0,0 +1,68 @@
+// Evol scripts.
+// Authors:
+// Ablu
+// Alastrim
+// Reid
+// Description:
+// Ratto killer.
+
+// $@ARTIS_RAT1_CONTROL array explanation:
+// [1] = Shows status of ratto number 1 (1 is dead and 0 is alive).
+// [2] = Shows status of ratto number 2 (1 is dead and 0 is alive).
+// [3] = Shows status of ratto number 3 (1 is dead and 0 is alive).
+// [4] = Shows status of ratto number 4 (1 is dead and 0 is alive).
+// [5] = Shows how many seconds passed since ratto number 1 died.
+// [6] = Shows how many seconds passed since ratto number 2 died.
+// [7] = Shows how many seconds passed since ratto number 3 died.
+// [8] = Shows how many seconds passed since ratto number 4 died.
+// [9] = Shows how many seconds passed since the player started the quest.
+
+001-2-23,47,30,0 script RattosControl#001-2-23 NPC_HIDDEN,{
+
+OnSpawn:
+ areamonster "001-2-23", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl#001-2-23::OnRatto1Death";
+ areamonster "001-2-23", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl#001-2-23::OnRatto2Death";
+ areamonster "001-2-23", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl#001-2-23::OnRatto3Death";
+ areamonster "001-2-23", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl#001-2-23::OnRatto4Death";
+ close;
+
+OnRatto1Respawn:
+ areamonster "001-2-23", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl#001-2-23::OnRatto1Death";
+ $@ARTIS_RAT1_CONTROL[1] = 0;
+ $@ARTIS_RAT1_CONTROL[5] = 0;
+ end;
+
+OnRatto2Respawn:
+ areamonster "001-2-23", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl#001-2-23::OnRatto2Death";
+ $@ARTIS_RAT1_CONTROL[2] = 0;
+ $@ARTIS_RAT1_CONTROL[6] = 0;
+ end;
+
+OnRatto3Respawn:
+ areamonster "001-2-23", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl#001-2-23::OnRatto3Death";
+ $@ARTIS_RAT1_CONTROL[3] = 0;
+ $@ARTIS_RAT1_CONTROL[7] = 0;
+ end;
+
+OnRatto4Respawn:
+ areamonster "001-2-23", 23, 19, 50, 40, "Ratto", 1005, 1, "RattosControl#001-2-23::OnRatto4Death";
+ $@ARTIS_RAT1_CONTROL[4] = 0;
+ $@ARTIS_RAT1_CONTROL[8] = 0;
+ end;
+
+OnRatto1Death:
+ $@ARTIS_RAT1_CONTROL[1] = 1;
+ end;
+
+OnRatto2Death:
+ $@ARTIS_RAT1_CONTROL[2] = 1;
+ end;
+
+OnRatto3Death:
+ $@ARTIS_RAT1_CONTROL[3] = 1;
+ end;
+
+OnRatto4Death:
+ $@ARTIS_RAT1_CONTROL[4] = 1;
+ end;
+}
diff --git a/npc/001-2-24/_import.txt b/npc/001-2-24/_import.txt
new file mode 100644
index 000000000..34c43a0b5
--- /dev/null
+++ b/npc/001-2-24/_import.txt
@@ -0,0 +1,7 @@
+// Map 001-2-24: Nard's Room
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-24/_warps.txt",
+"npc/001-2-24/hammock.txt",
+"npc/001-2-24/mapflags.txt",
+"npc/001-2-24/nard.txt",
+"npc/001-2-24/piourocket.txt",
diff --git a/npc/001-2-24/_warps.txt b/npc/001-2-24/_warps.txt
new file mode 100644
index 000000000..945c3aca1
--- /dev/null
+++ b/npc/001-2-24/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-24: Nard's Room warps
+001-2-24,19,27,0 warp #001-2-24_19_27 0,0,001-2-21,32,28
diff --git a/npc/001-2-24/hammock.txt b/npc/001-2-24/hammock.txt
new file mode 100644
index 000000000..f43193587
--- /dev/null
+++ b/npc/001-2-24/hammock.txt
@@ -0,0 +1,17 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Animated hammock at the top level of the ship.
+
+001-2-24,28,24,0 script #nardArtisHammock NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch:
+ hamTouchRight;
+
+OnUnTouch:
+ hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
diff --git a/npc/001-2-24/mapflags.txt b/npc/001-2-24/mapflags.txt
new file mode 100644
index 000000000..4506b385f
--- /dev/null
+++ b/npc/001-2-24/mapflags.txt
@@ -0,0 +1 @@
+001-2-24 mapflag town
diff --git a/npc/001-2-24/nard.txt b/npc/001-2-24/nard.txt
new file mode 100644
index 000000000..6c8458388
--- /dev/null
+++ b/npc/001-2-24/nard.txt
@@ -0,0 +1,94 @@
+// Evol scripts.
+// Authors:
+// Qwerty Dragon
+// Reid
+// Description:
+// Captain Nard dialogs.
+// Nard does the introduction with a small quest.
+// This quest is meant to teach the player how to use a weapon,and to bring food to the ship.
+// 4 bits array:
+// ShipQuests
+// Variable:
+// 0 ShipQuests_Nard
+// 1 ShipQuests_Gugli
+// 2 ShipQuests_ChefGado
+// Values:
+// 00 Introduction of the boxes and Nard. This is displayed when the player never spoke to Nard or his box.
+// 01 Nard spoke and gave access to the outdoor of the ship.
+// 02 Completed the Gugli quest.
+// 03 ChefGado Quest accepted.
+// 04 ChefGado Quest completed and "Introduction" chapter finalized.
+// 05 Reward taken from the box.
+// 10 Never talked with Gugli.
+// 11 Gugli gives you the task.
+// 12 Gave all of the boxes to Gugli.
+
+001-2-24,25,26,0 script Nard#Artis NPC_NARD,{
+
+ checkclientversion;
+ mesn;
+ mesq g(l("Good day miss."), l("Good day mister."));
+ next;
+ mesq l("What can I do for you?");
+ .@q = getq(ArtisQuests_Enora);
+
+ // Before the player sees Enora, the menu shows L_Lost on top
+ // If the player saw Enora, the menu shows L_Lost at the bottom
+ // Because he shouldn't be lost after having talked to her, so the priority in menu changes
+ menu
+ rif(.@q == 0, lg("I'm lost, where should I go?")), L_Lost,
+ rif(.@q > 0, l("Tell me, where are we right now?")), L_Info,
+ l("How long will you stay here?"), -,
+ rif(.@q > 0, lg("I'm lost, where should I go?")), L_Lost;
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("We just returned from a long journey and Artis is a good city to rest and to conclude our exchange."),
+ l("I think that we will stay in port for a great time."),
+ l("Although, if you want to visit a place nearby, we could take you there."),
+ l("Do you want to go somewhere?");
+
+ switch (select(l("Drasil Island."),
+ l("Nowhere, I'm fine here.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Let's set sail then!");
+
+ savepoint "000-2-1", 50, 38;
+ if (!getmapxy(.@map$, .@x, .@y, 0))
+ {
+ warp "000-2-3", .@x, .@y;
+ }
+ else
+ {
+ warp "000-2-3", 22, 27;
+ }
+
+ closedialog;
+ close;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Ok we stay docked here if you need our help.");
+
+ closedialog;
+ close;
+ }
+L_Info:
+ closedialog;
+ npctalk3 l("Don't you recognize the great city of Artis?");
+ close;
+
+L_Lost:
+ mes "";
+ mesn;
+ mesq l("Julia made an appeal to the Legion of Aemil to get in touch with you, exit the ship and you should see your escort!");
+ next;
+
+ closedialog;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 5;
+ end;
+}
diff --git a/npc/001-2-24/piourocket.txt b/npc/001-2-24/piourocket.txt
new file mode 100644
index 000000000..3bcc914bd
--- /dev/null
+++ b/npc/001-2-24/piourocket.txt
@@ -0,0 +1,9 @@
+// Evol scripts.
+// Author:
+// Ablu
+// Description:
+// Jumping piou.
+
+// actual source is in npc/000-2-3/piourocket.txt
+
+001-2-24,27,23,4 duplicate(#piourocket) #piourocketArtis NPC_PIOU_ROCKET
diff --git a/npc/001-2-25/_import.txt b/npc/001-2-25/_import.txt
new file mode 100644
index 000000000..a3e9ee03c
--- /dev/null
+++ b/npc/001-2-25/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-25: Storage Room
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-25/_mobs.txt",
+"npc/001-2-25/_warps.txt",
+"npc/001-2-25/mapflags.txt",
diff --git a/npc/001-2-25/_mobs.txt b/npc/001-2-25/_mobs.txt
new file mode 100644
index 000000000..de0c289e8
--- /dev/null
+++ b/npc/001-2-25/_mobs.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-25: Storage Room mobs
+001-2-25,0,0,0,0 monster Ratto 1005,2,240000,420000
diff --git a/npc/001-2-25/_warps.txt b/npc/001-2-25/_warps.txt
new file mode 100644
index 000000000..88fd273db
--- /dev/null
+++ b/npc/001-2-25/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-25: Storage Room warps
+001-2-25,29,31,0 warp #001-2-25_29_31 0,0,001-2-19,41,26
diff --git a/npc/001-2-25/mapflags.txt b/npc/001-2-25/mapflags.txt
new file mode 100644
index 000000000..659308e5e
--- /dev/null
+++ b/npc/001-2-25/mapflags.txt
@@ -0,0 +1 @@
+001-2-25 mapflag town
diff --git a/npc/001-2-26/_import.txt b/npc/001-2-26/_import.txt
new file mode 100644
index 000000000..ab0c29703
--- /dev/null
+++ b/npc/001-2-26/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-26: Alchemy Lab
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-26/_warps.txt",
+"npc/001-2-26/flask.txt",
+"npc/001-2-26/ivan.txt",
+"npc/001-2-26/mapflags.txt",
diff --git a/npc/001-2-26/_warps.txt b/npc/001-2-26/_warps.txt
new file mode 100644
index 000000000..2b16f5696
--- /dev/null
+++ b/npc/001-2-26/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-26: Alchemy Lab warps
+001-2-26,28,43,0 warp #001-2-26_28_43 0,0,001-1,163,71
diff --git a/npc/001-2-26/flask.txt b/npc/001-2-26/flask.txt
new file mode 100644
index 000000000..8afa58c3f
--- /dev/null
+++ b/npc/001-2-26/flask.txt
@@ -0,0 +1,21 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Alchemy animation.
+
+001-2-26,32,27,4 script #FlaskAlchemyLab NPC_FLASK,{
+ .dir = 2;
+ stopnpctimer;
+ initnpctimer;
+ close;
+
+OnTimer12920:
+ .dir = 4;
+ stopnpctimer;
+ end;
+
+OnInit:
+ .distance = 3;
+ end;
+}
diff --git a/npc/001-2-26/ivan.txt b/npc/001-2-26/ivan.txt
new file mode 100644
index 000000000..251e11073
--- /dev/null
+++ b/npc/001-2-26/ivan.txt
@@ -0,0 +1,86 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Alchemist NPC
+
+001-2-26,28,30,0 script Ivan NPC_IVAN,{
+
+ function ivan_description {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I am an alchemist, I bear the name of Ivan."),
+ l("I work under the protection and the supervision of the Legion of Aemil."),
+ l("Alchemical studies are prohibited in every city of the Archipelagos, do not dare to practice it in a public zone!");
+
+ return;
+ }
+
+ function enora_quest {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("How many? What kind? I can produce two dozen boxes per day.");
+
+ select(l("5 Piberries Infusions"));
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("5 boxes... Alright, @@ are my speciality!", getitemlink(PiberriesInfusion)),
+ l("I can prepare them in an hour or so!");
+
+ select(l("You missunderstood, it's 5 potions."));
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Why would the Legion request my help for only 5 potions?"),
+ l("Is this some kind of joke?!");
+
+ switch (select(l("Enora needs them."),
+ l("Excuse me that was a mistake.")))
+ {
+ case 1:
+ break;
+ case 2:
+ narrator S_FIRST_BLANK_LINE, l("Ivan grumbles and resumes his work.");
+ emotion E_UPSET;
+ close;
+ }
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh... You should have started with this!"),
+ l("I have some spare one, take them, and tell Enora that any fees are paid!");
+
+ setq ArtisQuests_Enora, 9;
+ emotion E_HAPPY;
+ return;
+ }
+
+ .@enora = getq(ArtisQuests_Enora);
+
+ if (.@enora < 8)
+ {
+ npctalk3 l("I'm busy, leave me alone.");
+ end;
+ }
+
+ speech S_LAST_NEXT, l("Yes what do you need?");
+
+ select
+ rif(.@enora == 8, l("The Legion needs some potions.")),
+ rif(.@enora >= 8, l("Who are you?")),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ enora_quest;
+ break;
+ case 2:
+ ivan_description;
+ break;
+ }
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-26/mapflags.txt b/npc/001-2-26/mapflags.txt
new file mode 100644
index 000000000..20c3188dc
--- /dev/null
+++ b/npc/001-2-26/mapflags.txt
@@ -0,0 +1 @@
+001-2-26 mapflag town
diff --git a/npc/001-2-27/_import.txt b/npc/001-2-27/_import.txt
new file mode 100644
index 000000000..977f41322
--- /dev/null
+++ b/npc/001-2-27/_import.txt
@@ -0,0 +1,8 @@
+// Map 001-2-27: Blacksmith Shop
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-27/_warps.txt",
+"npc/001-2-27/don.txt",
+"npc/001-2-27/kaylo.txt",
+"npc/001-2-27/lydon.txt",
+"npc/001-2-27/mapflags.txt",
+"npc/001-2-27/shop.txt",
diff --git a/npc/001-2-27/_warps.txt b/npc/001-2-27/_warps.txt
new file mode 100644
index 000000000..60537f046
--- /dev/null
+++ b/npc/001-2-27/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-27: Blacksmith Shop warps
+001-2-27,35,39,0 warp #001-2-27_35_35 0,0,001-1,101,108
diff --git a/npc/001-2-27/don.txt b/npc/001-2-27/don.txt
new file mode 100644
index 000000000..cc62f4c11
--- /dev/null
+++ b/npc/001-2-27/don.txt
@@ -0,0 +1,98 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Don the blacksmith of Artis
+
+001-2-27,35,29,0 script Don#001-2-27 NPC_HUMAN_MALE_OLD,{
+
+ function improve_equipment {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Different ways, each part of your equipment can be generally upgraded."),
+ l("You have a level for each of your gear, by default when you buy or craft a piece, the level is set to 1."),
+ l("You can also improve your equipment in a totally different way with the use of cards.");
+ return;
+ }
+
+ function card_explanation {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("There are two different kinds of cards, the first changes the style of your clothes, the second changes their stats."),
+ l("I am not an expert of the first kind, but I know what I am talking about when it comes to improving equipment."),
+ l("A stat card works on different pieces of equipment."),
+ l("Each piece of equipment has a predefined slot number."),
+ l("Each card improves your gear by a ratio or a fixed number on a predefined stat."),
+ l("Like, a defensive mythril card can be used on any mythril equipment, and it will improve the defense by 5% of the latter."),
+ l("You just have to select the card, then you choose which piece of equipment you want to use it on, and you are done.");
+ return;
+ }
+
+ function take_apprentice {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I do not.");
+ emotion E_UPSET;
+
+ select(l("What about Chelios?"));
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Chelios was stubborn in his youth, he never stopped annoying me with his questions while I was working at the forge."),
+ l("He did not change while growing up, I repeatedly asked him to leave the forge but in the end he installed himself in front of it..."),
+ l("He is mature and he rarely ask questions so I am fine. I can not stand the sight of a whiner anyway.");
+ return;
+ }
+
+ function good_blacksmith {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I do not like to brag about it but you won't find a better blacksmith on the whole island."),
+ l("If you need somebody to craft a weapon or a plate from diagrams I am the one that you need.");
+
+ switch (select(l("Can I craft them myself?"),
+ l("Ok.")))
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You can try, but your chance of success is lesser than a well trained smith and master craftsman.");
+ break;
+ case 2:
+ break;
+ }
+
+ return;
+ }
+
+ speech S_LAST_NEXT,
+ lg("Hi, what do you want kiddo?");
+
+ do
+ {
+ switch (.@q = select(l("How can I improve my equipment?"),
+ l("What is a card?"),
+ l("Are you a good blacksmith?"),
+ l("Do you take apprentices?"),
+ l("Nothing.")))
+ {
+ case 1:
+ improve_equipment;
+ break;
+ case 2:
+ card_explanation;
+ break;
+ case 3:
+ good_blacksmith;
+ break;
+ case 4:
+ take_apprentice;
+ break;
+ case 5:
+ break;
+ }
+ } while (.@q != 5);
+
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
+
diff --git a/npc/001-2-27/kaylo.txt b/npc/001-2-27/kaylo.txt
new file mode 100644
index 000000000..5134aa07e
--- /dev/null
+++ b/npc/001-2-27/kaylo.txt
@@ -0,0 +1,44 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Kaylo is the Shield seller in Don's Blacksmith house on Artis.
+
+001-2-27,27,28,0 script Kaylo#001-2-27 NPC_KAYLO,{
+ speech S_LAST_NEXT,
+ lg("Hi customer! What do you want today?");
+
+ switch (select(
+ l("Let's make a trade."),
+ l("What's wrong with your clothes?"),
+ l("What is this place?"),
+ l("See you.")))
+ {
+ case 1:
+ closedialog;
+ shop "Store#Shield001-2-27";
+ close;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I used a card to improve my clothes."),
+ l("There are two different kinds of cards, the first changes the style of your clothes, the second changes their stats."),
+ l("You should discuss with Don and Calypsan if you want to learn more about it, they are masters on this area!");
+ break;
+ case 3:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You are in the Blacksmith's house, by Jove!"),
+ l("Don is a renowned blacksmith throughout Andorra, it's crazy that you never heard of him.");
+ break;
+ case 4:
+ break;
+ }
+
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 4;
+ end;
+}
+
diff --git a/npc/001-2-27/lydon.txt b/npc/001-2-27/lydon.txt
new file mode 100644
index 000000000..3dcd8005c
--- /dev/null
+++ b/npc/001-2-27/lydon.txt
@@ -0,0 +1,37 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Lydon is the Weapon seller in Don's Blacksmith house on Artis.
+
+001-2-27,43,28,0 script Lydon#001-2-27 NPC_LYDON,{
+ speech S_LAST_NEXT,
+ lg("Hi customer! What do you want today?");
+
+ switch (select(
+ l("Let's make a trade."),
+ l("Who is the blacksmith outside?"),
+ l("Bye.")))
+ {
+ case 1:
+ closedialog;
+ shop "Store#Weapon001-2-27";
+ close;
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Chef? He is Don's apprentice, he works on his hammering skill day and night."),
+ l("He is very lucky that Don took him under his wing, but being the student of such a teacher is not easy every day!");
+ break;
+ case 3:
+ break;
+ }
+
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 4;
+ end;
+}
+
diff --git a/npc/001-2-27/mapflags.txt b/npc/001-2-27/mapflags.txt
new file mode 100644
index 000000000..42bba3662
--- /dev/null
+++ b/npc/001-2-27/mapflags.txt
@@ -0,0 +1 @@
+001-2-27 mapflag town
diff --git a/npc/001-2-27/shop.txt b/npc/001-2-27/shop.txt
new file mode 100644
index 000000000..597fd06b8
--- /dev/null
+++ b/npc/001-2-27/shop.txt
@@ -0,0 +1,60 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Blacksmith shops
+
+001-2-27,27,29,0 trader Store#Shield001-2-27 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem LeatherShield, -1, 30;
+ sellitem CopperArmbands, -1, 28;
+ sellitem IronArmbands, -1, 20;
+
+ .sex = G_OTHER;
+ .distance = 2;
+ end;
+
+OnClock0000:
+ restoreshopitem LeatherShield, 10;
+ restoreshopitem CopperArmbands, 9;
+ restoreshopitem IronArmbands, 7;
+OnClock0800:
+ restoreshopitem LeatherShield, 10;
+ restoreshopitem CopperArmbands, 6;
+ restoreshopitem IronArmbands, 3;
+OnClock01600:
+ restoreshopitem LeatherShield, 10;
+ restoreshopitem CopperArmbands, 8;
+ restoreshopitem IronArmbands, 6;
+}
+
+001-2-27,43,29,0 trader Store#Weapon001-2-27 NPC_NO_SPRITE,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem PiouSlayer, -1, 50;
+ sellitem TrainingGladius, -1, 25;
+ sellitem WoodenSword, -1, 50;
+
+ .sex = G_OTHER;
+ .distance = 2;
+ end;
+
+OnClock0000:
+ restoreshopitem PiouSlayer, 25;
+ restoreshopitem TrainingGladius, 8;
+ restoreshopitem WoodenSword, 25;
+OnClock0800:
+ restoreshopitem PiouSlayer, 25;
+ restoreshopitem TrainingGladius, 8;
+ restoreshopitem WoodenSword, 25;
+OnClock01600:
+ restoreshopitem PiouSlayer, 25;
+ restoreshopitem TrainingGladius, 8;
+ restoreshopitem WoodenSword, 25;
+}
diff --git a/npc/001-2-28/_import.txt b/npc/001-2-28/_import.txt
new file mode 100644
index 000000000..a58d3feec
--- /dev/null
+++ b/npc/001-2-28/_import.txt
@@ -0,0 +1,8 @@
+// Map 001-2-28: Red Plush Inn
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-28/_warps.txt",
+"npc/001-2-28/jenna.txt",
+"npc/001-2-28/mapflags.txt",
+"npc/001-2-28/note.txt",
+"npc/001-2-28/plush.txt",
+"npc/001-2-28/shop.txt",
diff --git a/npc/001-2-28/_warps.txt b/npc/001-2-28/_warps.txt
new file mode 100644
index 000000000..4447ee632
--- /dev/null
+++ b/npc/001-2-28/_warps.txt
@@ -0,0 +1,5 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-28: Red Plush Inn warps
+001-2-28,29,42,0 warp #001-2-28_29_42 0,0,001-1,118,89
+001-2-28,61,30,0 warp #001-2-28_61_30 0,0,001-1,135,83
+001-2-28,34,25,0 warp #001-2-28_34_25 3,0,001-2-29,38,34
diff --git a/npc/001-2-28/jenna.txt b/npc/001-2-28/jenna.txt
new file mode 100644
index 000000000..4beb0604b
--- /dev/null
+++ b/npc/001-2-28/jenna.txt
@@ -0,0 +1,79 @@
+// Evol scripts.
+// Author:
+// Travolta
+// Description:
+// Jenna, waitress in Artis inn.
+
+001-2-28,52,32,0 script Jenna#001-2-28 NPC_RAIJIN_FEMALE_WAITRESS,1,1,{
+
+ function SayRandomGreeting {
+
+ .@tick = gettimetick(1);
+ if (.@tick > @Artis_RedPlush_WaitressTick + 10)
+ {
+ setarray .messages$[0], l("Welcome to our inn!"),
+ l("Welcome to Red Plush."),
+ l("Please, have a seat."),
+ l("Lovely day, isn't it?");
+
+ .@r = rand(getarraysize(.messages$));
+ .@msg$ = .messages$[.@r];
+ npctalk3 .@msg$;
+ @Artis_RedPlush_WaitressTick = .@tick;
+ }
+ }
+
+ speech S_LAST_NEXT, l("Do you want a drink?");
+
+ closedialog;
+ shop "#Invisible001-2-28";
+ close;
+
+OnTimer1000:
+ dographmovestep;
+
+OnTouch:
+ SayRandomGreeting;
+ end;
+
+OnHour00:
+ if (playerattached())
+ @Artis_RedPlush_WaitressTick = 0;
+ end;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 5;
+ initmovegraph "m_table_1", 52, 32,
+ "m_table_2", 56, 32,
+ "big_table_l", 53, 27,
+ "big_table_r", 56, 30,
+ "s_table_1", 53, 36,
+ "s_table_2", 58, 38,
+ "lf_table_2", 45, 31;
+
+ setmovegraphcmd "m_table_1", "s_table_2", 2, "dir 4; wait 8",
+ "m_table_1", "lf_table_2", 1, "dir 4; wait 8",
+ "m_table_1", "big_table_l",1, "dir 0; wait 10",
+ "m_table_2", "m_table_1", 1, "dir 0; wait 8",
+ "m_table_2", "lf_table_2", 1, "dir 4; emote 2; wait 8",
+ "m_table_2", "big_table_l",2, "dir 0; wait 8",
+ "s_table_1", "m_table_1", 5, "dir 0; wait 10",
+ "s_table_1", "big_table_l",3, "dir 0; wait 1; emote 103;"
+ "say Thank you for the tip!;"
+ "wait 15; moveon",
+ "s_table_1", "m_table_2", 1, "dir 0; wait 8",
+ "s_table_2", "s_table_1", 1, "wait 6",
+ "s_table_2", "m_table_2", 1, "dir 0; wait 8",
+ "big_table_l", "m_table_2", 1, "dir 0; wait 6",
+ "big_table_l", "s_table_1", 1, "dir 2; wait 6",
+ "big_table_r", "s_table_1", 1, "dir 2; wait 6",
+ "big_table_r", "m_table_2", 2, "wait 8",
+ "big_table_r", "s_table_2", 1, "dir 4; wait 8",
+ "lf_table_2", "m_table_2", 1, "dir 0; wait 8",
+ "lf_table_2", "big_table_r",1, "dir 4; wait 1; emote 3; wait 6";
+
+ firstmove "wait 8";
+ initnpctimer;
+}
+
diff --git a/npc/001-2-28/mapflags.txt b/npc/001-2-28/mapflags.txt
new file mode 100644
index 000000000..8cf7ec216
--- /dev/null
+++ b/npc/001-2-28/mapflags.txt
@@ -0,0 +1 @@
+001-2-28 mapflag town
diff --git a/npc/001-2-28/note.txt b/npc/001-2-28/note.txt
new file mode 100644
index 000000000..c57a3f21e
--- /dev/null
+++ b/npc/001-2-28/note.txt
@@ -0,0 +1,25 @@
+// Evol scripts.
+// Authors:
+// gumi
+// Qwerty Dragon
+// Reid
+// WildX
+// Description:
+// A small note presenting the 7 main rules of Evol Online.
+
+001-2-28,36,28,0 script Note#001-2-28 NPC_PAPER_NOTE,{
+ narrator S_LAST_NEXT,
+ l("There is a paper with some rules written on it.");
+
+ GameRules 8 | 4;
+
+ narrator S_NO_NPC_NAME,
+ l("Following these lines are some other writings on this paper."),
+ l("Do not give the password of your room to anybody! Keep it secret and try not to use the same one in any other room in the future. - Jenna");
+
+ close;
+
+OnInit:
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-28/plush.txt b/npc/001-2-28/plush.txt
new file mode 100644
index 000000000..5600f2f24
--- /dev/null
+++ b/npc/001-2-28/plush.txt
@@ -0,0 +1,130 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Red, the Innkeeper.
+// Variable:
+// INN_REGISTER
+
+001-2-28,28,28,0 script Plush#001-2-28 NPC_RED,{
+
+ function narrator_explication {
+ narrator S_LAST_NEXT,
+ l("You will respawn at this place if defeated in combat."),
+ l("All you have to do is to select a bed in the upper level anytime after your reservation."),
+ l("Unlike other respawn points, an inn can fully restore your HP."),
+ l("Of course, you can select a bed somewhere else after your reservation, but you won't get your HP recovery until you choose to get some rest in the inn."),
+ l("You can also use your room to get some rest after a long battle. That will consume your reservation but your HP will be fully restored.");
+ return;
+ }
+
+ function accepted_room {
+ .@price = getarg(0);
+ if (Zeny < .@price)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("You don't have enough money, bring @@ E.", .@price);
+ }
+ else
+ {
+ emotion E_HAPPY;
+ Zeny = Zeny - .@price;
+ INN_REGISTER = REDPLUSH_INN;
+ PC_IS_DEAD = false;
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("I registered you on the 4th room of the upper level.",
+ "I registered you on the 2nd room of the upper level."),
+ l("You can go upstairs and choose a different room if you want.");
+ savepoint "001-2-29", 29, g(49, 35);
+ }
+ }
+
+ function register_room {
+ .@price = lognbaselvl(100, 10);
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("That will be @@ E to set your respawn point", .@price),
+ l("This will remain your respawn point until set elsewhere."),
+ l("Is that okay?");
+
+ if (askyesno() == ASK_YES)
+ {
+ accepted_room(.@price);
+ }
+ else
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Come back later if you changed your mind!");
+ }
+
+ return;
+ }
+
+ function lodge_check {
+ if (INN_REGISTER == NO_INN)
+ {
+ register_room;
+ }
+ else if (INN_REGISTER == REDPLUSH_INN)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("You are already registered here."),
+ l("Go on the upper level if you want to change your room or to use it.");
+ }
+ else
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("If you are registered somewhere else you will loose that reservation."),
+ l("Do you still want to lodge here?");
+
+ if (askyesno() == ASK_YES)
+ {
+ register_room;
+ }
+ }
+ return;
+ }
+
+ speech S_LAST_NEXT,
+ l("Welcome to the Red Plush inn!"),
+ l("What do you need?");
+
+ do
+ {
+ .@q = select(
+ l("Could I lodge here for a while?"),
+ l("What service do you offer?"),
+ l("What is your tipiou trying to do?"),
+ l("Nothing."));
+
+ switch (.@q)
+ {
+ case 1:
+ lodge_check;
+ break;
+ case 2:
+ emotion E_WINK;
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("We offer a room for travelers passing by Artis, our beds are comfy and you can be guaranteed to be right as rain after a night here!"),
+ l("If you wake up at the inn after a harsh battle, you will find yourself revitalized in an instant unlike other places where you can rest.");
+
+ narrator_explication;
+ break;
+ case 3:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("That poor one is doing his best to fly... But his last meal and the gravity is not helping him so far!");
+ break;
+ case 4:
+ break;
+ }
+ } while (.@q != 1 && .@q != 4);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 5;
+}
+
diff --git a/npc/001-2-28/shop.txt b/npc/001-2-28/shop.txt
new file mode 100644
index 000000000..1d435c314
--- /dev/null
+++ b/npc/001-2-28/shop.txt
@@ -0,0 +1,25 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Inn hidden shop.
+
+001-2-28,53,33,0 trader #Invisible001-2-28 NPC_HIDDEN,{
+
+OnInit:
+ tradertype(NST_MARKET);
+
+ sellitem RedPlushWine, -1, 50;
+
+ .sex = G_OTHER;
+ .distance = 10;
+ end;
+
+OnClock0000:
+ restoreshopitem RedPlushWine, 20;
+OnClock0800:
+ restoreshopitem RedPlushWine, 20;
+OnClock1600:
+ restoreshopitem RedPlushWine, 20;
+}
diff --git a/npc/001-2-29/_import.txt b/npc/001-2-29/_import.txt
new file mode 100644
index 000000000..39bb3601c
--- /dev/null
+++ b/npc/001-2-29/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-29: First Floor
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-29/_warps.txt",
+"npc/001-2-29/mapflags.txt",
+"npc/001-2-29/savepoint.txt",
diff --git a/npc/001-2-29/_warps.txt b/npc/001-2-29/_warps.txt
new file mode 100644
index 000000000..6c9d08f9b
--- /dev/null
+++ b/npc/001-2-29/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-29: First Floor warps
+001-2-29,39,35,0 warp #001-2-29_39_35 3,0,001-2-28,33,27
+001-2-29,38,25,0 warp #001-2-29_38_25 0,1,001-2-30,36,31
diff --git a/npc/001-2-29/mapflags.txt b/npc/001-2-29/mapflags.txt
new file mode 100644
index 000000000..98a4373fe
--- /dev/null
+++ b/npc/001-2-29/mapflags.txt
@@ -0,0 +1 @@
+001-2-29 mapflag town
diff --git a/npc/001-2-29/savepoint.txt b/npc/001-2-29/savepoint.txt
new file mode 100644
index 000000000..4694e31ea
--- /dev/null
+++ b/npc/001-2-29/savepoint.txt
@@ -0,0 +1,53 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Saves locations in 001-2-29 map.
+
+001-2-29,29,28,0 script #001-2-29-1 NPC_SAVE_POINT,0,0,{
+ bedClic("001-2-29", 29, 28, REDPLUSH_INN);
+
+OnInit:
+ .distance = 2;
+ end;
+
+OnTouch:
+ bedTouch;
+
+OnPCDieEvent:
+ PC_IS_DEAD = 1;
+ close;
+}
+
+001-2-29,29,35,0 script #001-2-29-2 NPC_SAVE_POINT,0,0,{
+ bedClic("001-2-29", 29, 35, REDPLUSH_INN);
+
+OnInit:
+ .distance = 2;
+ end;
+
+OnTouch:
+ bedTouch;
+}
+
+001-2-29,29,42,0 script #001-2-29-3 NPC_SAVE_POINT,0,0,{
+ bedClic("001-2-29", 29, 42, REDPLUSH_INN);
+
+OnInit:
+ .distance = 2;
+ end;
+
+OnTouch:
+ bedTouch;
+}
+
+001-2-29,29,49,0 script #001-2-29-4 NPC_SAVE_POINT,0,0,{
+ bedClic("001-2-29", 29, 49, REDPLUSH_INN);
+
+OnInit:
+ .distance = 2;
+ end;
+
+OnTouch:
+ bedTouch;
+}
diff --git a/npc/001-2-3/_import.txt b/npc/001-2-3/_import.txt
new file mode 100644
index 000000000..c003e206d
--- /dev/null
+++ b/npc/001-2-3/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-3: First Floor
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-3/_savepoints.txt",
+"npc/001-2-3/_warps.txt",
+"npc/001-2-3/mapflags.txt",
diff --git a/npc/001-2-3/_savepoints.txt b/npc/001-2-3/_savepoints.txt
new file mode 100644
index 000000000..a3e08055e
--- /dev/null
+++ b/npc/001-2-3/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-3: First Floor saves
+001-2-3,42,32,0 script #save_001-2-3_42_32 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-2-3/_warps.txt b/npc/001-2-3/_warps.txt
new file mode 100644
index 000000000..ddd0b6e17
--- /dev/null
+++ b/npc/001-2-3/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-3: First Floor warps
+001-2-3,27,31,0 warp #001-2-3_27_31 2,0,001-2-2,27,31
diff --git a/npc/001-2-3/mapflags.txt b/npc/001-2-3/mapflags.txt
new file mode 100644
index 000000000..311c2c75a
--- /dev/null
+++ b/npc/001-2-3/mapflags.txt
@@ -0,0 +1 @@
+001-2-3 mapflag town
diff --git a/npc/001-2-30/_import.txt b/npc/001-2-30/_import.txt
new file mode 100644
index 000000000..91918ef55
--- /dev/null
+++ b/npc/001-2-30/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-30: Second Floor
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-30/_mobs.txt",
+"npc/001-2-30/_warps.txt",
+"npc/001-2-30/mapflags.txt",
diff --git a/npc/001-2-30/_mobs.txt b/npc/001-2-30/_mobs.txt
new file mode 100644
index 000000000..956ecf5df
--- /dev/null
+++ b/npc/001-2-30/_mobs.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-30: Second Floor mobs
+001-2-30,0,0,0,0 monster Ratto 1005,1,240000,420000
diff --git a/npc/001-2-30/_warps.txt b/npc/001-2-30/_warps.txt
new file mode 100644
index 000000000..60c227f82
--- /dev/null
+++ b/npc/001-2-30/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-30: Second Floor warps
+001-2-30,37,32,0 warp #001-2-30_37_32 1,0,001-2-29,37,27
diff --git a/npc/001-2-30/mapflags.txt b/npc/001-2-30/mapflags.txt
new file mode 100644
index 000000000..357de0aad
--- /dev/null
+++ b/npc/001-2-30/mapflags.txt
@@ -0,0 +1 @@
+001-2-30 mapflag town
diff --git a/npc/001-2-31/_import.txt b/npc/001-2-31/_import.txt
new file mode 100644
index 000000000..a599f2ae4
--- /dev/null
+++ b/npc/001-2-31/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-2-31: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-31/_warps.txt",
+"npc/001-2-31/mapflags.txt",
diff --git a/npc/001-2-31/_warps.txt b/npc/001-2-31/_warps.txt
new file mode 100644
index 000000000..b25ab8886
--- /dev/null
+++ b/npc/001-2-31/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-31: unnamed warps
+001-2-31,32,40,0 warp #001-2-31_32_40 0,0,001-1,49,97
+001-2-31,36,32,0 warp #001-2-31_36_32 0,0,001-2-41,25,32
diff --git a/npc/001-2-31/mapflags.txt b/npc/001-2-31/mapflags.txt
new file mode 100644
index 000000000..a7f187822
--- /dev/null
+++ b/npc/001-2-31/mapflags.txt
@@ -0,0 +1 @@
+001-2-31 mapflag town
diff --git a/npc/001-2-32/_import.txt b/npc/001-2-32/_import.txt
new file mode 100644
index 000000000..9043352d9
--- /dev/null
+++ b/npc/001-2-32/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-32: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-32/_warps.txt",
+"npc/001-2-32/doors.txt",
+"npc/001-2-32/mapflags.txt",
+"npc/001-2-32/serena.txt",
diff --git a/npc/001-2-32/_warps.txt b/npc/001-2-32/_warps.txt
new file mode 100644
index 000000000..306493cb8
--- /dev/null
+++ b/npc/001-2-32/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-32: unnamed warps
+001-2-32,27,33,0 warp #001-2-32_27_33 0,0,001-2-33,39,33
diff --git a/npc/001-2-32/doors.txt b/npc/001-2-32/doors.txt
new file mode 100644
index 000000000..59ee35eb3
--- /dev/null
+++ b/npc/001-2-32/doors.txt
@@ -0,0 +1,23 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Doors NPCs.
+
+001-2-32,33,29,0 script ToFightRoom#001-2-32 NPC_HIDDEN,0,0,{
+
+OnTouch:
+ if (mobcount("001-2-35","all") > 0)
+ {
+ narrator
+ l("You hear some sound behind the door."),
+ l("Somebody is probably training, better wait for him to finish.");
+ }
+ else
+ {
+ warp "001-2-35", 24, 29;
+ }
+
+ closedialog;
+ close;
+}
diff --git a/npc/001-2-32/mapflags.txt b/npc/001-2-32/mapflags.txt
new file mode 100644
index 000000000..8225ecbe2
--- /dev/null
+++ b/npc/001-2-32/mapflags.txt
@@ -0,0 +1 @@
+001-2-32 mapflag town
diff --git a/npc/001-2-32/serena.txt b/npc/001-2-32/serena.txt
new file mode 100644
index 000000000..187a654ce
--- /dev/null
+++ b/npc/001-2-32/serena.txt
@@ -0,0 +1,60 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Artis's Legion of Aemil officier of the fighting room.
+
+001-2-32,27,27,0 script Serena NPC_SERENA,{
+ mesn;
+ mesq lg("Oh darling, what brought you here?");
+ // ^^^^^^^
+ // Expresses familiarity or elderliness in relation to PC.
+
+ // <scratch>
+ // [ PC]: I was just looking around.
+ // [NPC]: Did not someone offer guidance?
+ // [NPC]: Enora was supposed to be helping you...
+ // [NPC]: ...but, she is young, and often absent-minded; did you ask?
+ // [NPC]: (Alt.) It seems you rushed ahead of her. Go back and talk to Enora.
+ // ([Enora]: Beyond here is the fighting room o_o;)
+ // ([Enora]: I... uh... well, you will need alies in there.)
+ // ([Enora]: And... you see... this is my good outfit and...)
+ // ([Enora]: ...I've only just cleaned up in there >.>)
+ // But if you keep getting stronger; that will be the day.
+
+ // Alt-Ready:
+ // [NPC]: Beyond here is the Fight Room.
+ // [NPC]: [conditions]*
+ // [NPC]: Good-luck | Bonne-chance.
+
+ // (Alt.) [NPC]: I used to be an adventurer, like you.
+ // [NPC]: But there was no one to join for quests.
+ // [NPC]: So I enlisted for a post at this chapter.
+ // [NPC]: But my "friends" joined the Brotherhood!
+
+ // [NPC]: The Brotherhood knows a lot more about monsters.
+ // [NPC]: But they could not "break the Legion's power" without burning all cities to the ground.
+ // [NPC]: The cities grow fast, ruining farmers and peasants.
+ // [NPC]: Our differences lead to friction.
+
+ // Alt-What
+ // The secret is out: We really did create a mutant.
+ // None of the members were informed until it went out-of-control.
+ // [...]
+ // Muahaha-ha! My beautiful mutant. The city of Artis is mine.
+ // </scratch>
+
+ // Alt-Siege
+ // The city is being attacked. Go help the warriors and town-guard.
+
+ goto L_Close;
+
+L_Close:
+ close;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-2-33/_import.txt b/npc/001-2-33/_import.txt
new file mode 100644
index 000000000..7dadf6f85
--- /dev/null
+++ b/npc/001-2-33/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-33: Legion of Aemil Headquarters
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-33/_warps.txt",
+"npc/001-2-33/lozerk.txt",
+"npc/001-2-33/mapflags.txt",
+"npc/001-2-33/triggers.txt",
diff --git a/npc/001-2-33/_warps.txt b/npc/001-2-33/_warps.txt
new file mode 100644
index 000000000..0f913422c
--- /dev/null
+++ b/npc/001-2-33/_warps.txt
@@ -0,0 +1,53 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-33: Legion of Aemil Headquarters warps
+001-2-33,29,32,0 script #001-2-33_29_32_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-34", 29, 32;
+close;
+
+OnUnTouch:
+ doevent "#001-2-33_29_32::OnUnTouch";
+}
+001-2-33,29,32,0 script #001-2-33_29_32 NPC_ARTIS_IN_DOOR,1,2,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-2-33,39,32,0 script #001-2-33_39_32_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-32", 27, 32;
+close;
+
+OnUnTouch:
+ doevent "#001-2-33_39_32::OnUnTouch";
+}
+001-2-33,39,32,0 script #001-2-33_39_32 NPC_ARTIS_IN_DOOR,1,2,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
+001-2-33,45,28,0 warp #001-2-33_45_28 0,0,001-2-38,24,28
+001-2-33,23,28,0 warp #001-2-33_23_28 0,0,001-2-37,36,28
+001-2-33,25,44,0 warp #001-2-33_25_40 2,0,001-2-40,27,46
+001-2-33,43,40,0 warp #001-2-33_43_40 2,0,001-2-40,45,46
+001-2-33,34,46,0 warp #001-2-33_34_46 0,0,001-1,57,42
diff --git a/npc/001-2-33/lozerk.txt b/npc/001-2-33/lozerk.txt
new file mode 100644
index 000000000..6eb9cb372
--- /dev/null
+++ b/npc/001-2-33/lozerk.txt
@@ -0,0 +1,188 @@
+// Evol scripts.
+// Authors:
+// monwarez
+// Reid
+// Tirifto
+// Description:
+// Sword trainer from the Legion of Aemil guild.
+// Variables:
+// Artis_Legion_Progress
+// Values:
+// 0 Default.
+// 1 Sent to training.
+// 2 Finished training.
+// 3 Sent to battle.
+// 4 Finished battle.
+// 5 Sent to Q'Anon.
+
+001-2-33,34,33,0 script Lozerk NPC_DEMON_MALE_SWORD,{
+
+ // Quest-related functions
+
+ function explain_direction {
+
+ switch (getq(Artis_Legion_Progress))
+ {
+ case 1:
+ setcamnpc "#001-2-33_29_32";
+
+ speech(S_LAST_NEXT | S_NO_NPC_NAME,
+ l("It's to the west, on your left side. Just go through this door before the stairs and turn left afterwards. Can't miss it!"),
+ l("Talk to Hector and he'll show you the ropes."),
+ l("Report back to me once you've had enough!"));
+
+ restorecam;
+
+ break;
+ case 3:
+ setcamnpc "#001-2-33_39_32";
+
+ speech(S_LAST_NEXT | S_NO_NPC_NAME,
+ l("The room is to the east, on your right side. Just go through the door before the stairs and then turn right. It's like the mirror image of our training room."));
+
+ restorecam;
+ break;
+ case 5:
+ setcamnpc "#001-2-33_45_28";
+
+ speech(S_LAST_NEXT | S_NO_NPC_NAME,
+ l("Walk up the stairs, go through the door on either side, and the only other door in the room, few steps to the south, will lead you right to him."));
+
+ restorecam;
+ break;
+ }
+
+ return;
+ }
+
+ function send_training {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("Oh, you were sent by Enora!"),
+ l("If Enora thinks this is the right place for you, then she's probably be right. Did you know she's a lieutenant of the Legion?"),
+ l("The rank of lieutenant is granted only to people with proper control of their skill and good judgment, like Enora. Or me, of course."),
+ l("By the way, I'm Lozerk. Lieutenant Lozerk.");
+
+ select(l("Pleasure to meet you. I am @@.", strcharinfo(PC_NAME)));
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("Oh, you are that person! You were stranded in the seas for a while, right? You look like it."),
+ l("But don't you worry! I don't know how to get you back your memories, but we can work on your muscles for now!"),
+ lg("After all, this is the Legion of Aemil! You want to be a great warrior? We'll make you one here!"),
+ l("For starters, you should probably do some stretching and practice on some dummies in our training room."),
+ l("That's right, we have our very own training room. The Legion is always well prepared!");
+
+ setq Artis_Legion_Progress, 1;
+ explain_direction();
+
+ return;
+ }
+
+ function send_battle {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("So, did you get your blood boiling? Give the dummies a good lesson? Good!"),
+ l("But since it's not dummies that will go after you out there, this training won't be enough."),
+ lg("If you want to make a formidable foe for anyone, you'll need to train with real living opponents!"),
+ l("Of course, the Legion of Aemil can easily provide you with such training, even if you're not a member. Just great, isn't it?"),
+ l("We have a special room for this purpose, too. You may test your skills against all kinds of dreadful monsters in there.");
+
+ setq Artis_Legion_Progress, 3;
+ explain_direction();
+
+ return;
+ }
+
+ function send_qanon {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("And you won! That means you should be able to handle yourself in battle from now on."),
+ lg("If you keep it up, you'll eventually become a fearsome warrior, just like me!"),
+ l("Or almost like me, at the very least."),
+ l("But if you really want to accomplish something, you should consider joining us."),
+ l("You have talent and the best place to utilize it is in the Legion! You can either pursue your goals with us or without us, but trust me, with us it's much better."),
+ l("I should know, I've not been a member for a while, too. But then I joined the Legion and look what a shining example of a great fighter I became!"),
+ l("You should definitely go talk to Q'Anon, our boss. You'll find him upstairs.");
+
+ setq Artis_Legion_Progress, 5;
+ explain_direction();
+
+ return;
+ }
+
+ // Normal functions
+
+ function forget_direction {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ lg("You are lucky there are no mental faculty requirements to join the Legion!");
+
+ explain_direction;
+
+ return;
+ }
+
+ function tell_about_legion {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("The Legion of Aemil is the greatest organization on all continent! A town cannot be safer than when it's under our protection."),
+ l("This is where the bravest of warriors come together to put their skills to a good use, for a good cause."),
+ l("Our building here is also the finest place in the town. Just go and see for yourself!");
+
+ return;
+ }
+
+ function praise_sword {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Thanks!");
+
+ return;
+ }
+
+ // Conversation
+
+ speech S_LAST_NEXT,
+ l("Welcome to the Legion of Aemil's building in Artis!");
+
+ do
+ {
+ .@legion_progress = getq(Artis_Legion_Progress);
+ .@enora = getq(ArtisQuests_Enora);
+ debugmes .@legion_progress + " " + .@enora;
+ select
+ rif((.@legion_progress == 0) && (.@enora == 11), lg("Enora sent me here.")),
+ rif(.@legion_progress == 2, lg("I'm done with my training.")),
+ rif(.@legion_progress == 4, lg("I'm back from battle!")),
+ rif(.@legion_progress == 1 || .@legion_progress == 3 || .@legion_progress == 5, l("Where should I go?")),
+ l("What can you tell me about the legion?"),
+ l("That's a nice sword you have there."),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ send_training;
+ break;
+ case 2:
+ send_battle;
+ break;
+ case 3:
+ send_qanon;
+ break;
+ case 4:
+ forget_direction;
+ break;
+ case 5:
+ tell_about_legion;
+ break;
+ case 6:
+ praise_sword;
+ break;
+ }
+ } while(@menu != 7);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-2-33/mapflags.txt b/npc/001-2-33/mapflags.txt
new file mode 100644
index 000000000..95e3a6ba6
--- /dev/null
+++ b/npc/001-2-33/mapflags.txt
@@ -0,0 +1,2 @@
+001-2-33 mapflag mask 5
+001-2-33 mapflag town
diff --git a/npc/001-2-33/triggers.txt b/npc/001-2-33/triggers.txt
new file mode 100644
index 000000000..47a5ea900
--- /dev/null
+++ b/npc/001-2-33/triggers.txt
@@ -0,0 +1,101 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Artis Aemil's Legion triggers to add and remove masks.
+
+// Transition Top triggers
+001-2-33,26,35,0 script #001-2-33LeftRemTop NPC_HIDDEN,0,2,{
+OnTouch:
+ artisALRemTopMask;
+ close;
+}
+
+001-2-33,27,35,0 script #001-2-33LeftAddTop NPC_HIDDEN,0,2,{
+OnTouch:
+ artisALAddTopMask;
+ close;
+}
+
+001-2-33,42,35,0 script #001-2-33RightRemTop NPC_HIDDEN,0,2,{
+OnTouch:
+ artisALRemTopMask;
+ close;
+}
+
+001-2-33,41,35,0 script #001-2-33RightAddTop NPC_HIDDEN,0,2,{
+OnTouch:
+ artisALAddTopMask;
+ close;
+}
+
+// Transition Bottom triggers
+
+001-2-33,25,32,0 script #001-2-33LeftRemBot NPC_HIDDEN,1,0,{
+OnTouch:
+ artisALRemBotMask;
+ close;
+}
+
+001-2-33,25,31,0 script #001-2-33LeftAddBot NPC_HIDDEN,1,0,{
+OnTouch:
+ artisALAddBotMask;
+ close;
+}
+
+001-2-33,43,32,0 script #001-2-33RightRemBot NPC_HIDDEN,1,0,{
+OnTouch:
+ artisALRemBotMask;
+ close;
+}
+
+001-2-33,43,31,0 script #001-2-33RightAddBot NPC_HIDDEN,1,0,{
+OnTouch:
+ artisALAddBotMask;
+ close;
+}
+
+// Warped location triggers
+
+001-2-33,24,30,0 script #001-2-33WarpTopLeft NPC_HIDDEN,1,1,{
+OnTouch:
+ artisALUpdateMask;
+ close;
+}
+
+001-2-33,44,30,0 script #001-2-33WarpTopRight NPC_HIDDEN,1,1,{
+OnTouch:
+ artisALUpdateMask;
+ close;
+}
+
+001-2-33,29,32,0 script #001-2-33WarpMidLeft NPC_HIDDEN,1,1,{
+OnTouch:
+ artisALUpdateMask;
+ close;
+}
+
+001-2-33,39,32,0 script #001-2-33WarpMidRight NPC_HIDDEN,1,1,{
+OnTouch:
+ artisALUpdateMask;
+ close;
+}
+
+001-2-33,34,45,0 script #001-2-33WarpArtis NPC_HIDDEN,1,1,{
+OnTouch:
+ artisALUpdateMask;
+ close;
+}
+
+// Bottom Warp location triggers
+001-2-33,43,38,0 script #001-2-33WarpBotLeft NPC_HIDDEN,1,0,{
+OnTouch:
+ artisALUpdateMask;
+ close;
+}
+
+001-2-33,25,38,0 script #001-2-33WarpBotRight NPC_HIDDEN,1,0,{
+OnTouch:
+ artisALUpdateMask;
+ close;
+}
diff --git a/npc/001-2-34/_import.txt b/npc/001-2-34/_import.txt
new file mode 100644
index 000000000..326973e61
--- /dev/null
+++ b/npc/001-2-34/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-34: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-34/_warps.txt",
+"npc/001-2-34/doors.txt",
+"npc/001-2-34/mapflags.txt",
+"npc/001-2-34/samantha.txt",
diff --git a/npc/001-2-34/_warps.txt b/npc/001-2-34/_warps.txt
new file mode 100644
index 000000000..1311f071d
--- /dev/null
+++ b/npc/001-2-34/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-34: unnamed warps
+001-2-34,29,33,0 warp #001-2-34_29_33 0,0,001-2-33,29,33
diff --git a/npc/001-2-34/doors.txt b/npc/001-2-34/doors.txt
new file mode 100644
index 000000000..3e4fef7bd
--- /dev/null
+++ b/npc/001-2-34/doors.txt
@@ -0,0 +1,29 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Doors NPCs.
+
+001-2-34,23,29,0 script ToTrainingRoom#001-2-34 NPC_HIDDEN,0,0,{
+
+OnTouch:
+ if ((getmapusers($@MAP_NAME$) == 0) && ($@FightingIsActive > 0))
+ {
+ set $@FightingIsActive, 0;
+ killmonsterall "001-2-36";
+ }
+
+ if (mobcount("001-2-36","all") > 0 && $@FightingIsActive > 0)
+ {
+ narrator
+ l("You hear some sound behind the door."),
+ l("Somebody is probably training, better wait for him to finish.");
+ }
+ else
+ {
+ warp "001-2-36", 36, 30;
+ }
+
+ closedialog;
+ close;
+}
diff --git a/npc/001-2-34/mapflags.txt b/npc/001-2-34/mapflags.txt
new file mode 100644
index 000000000..b632f6fe6
--- /dev/null
+++ b/npc/001-2-34/mapflags.txt
@@ -0,0 +1 @@
+001-2-34 mapflag town
diff --git a/npc/001-2-34/samantha.txt b/npc/001-2-34/samantha.txt
new file mode 100644
index 000000000..f49e15aa4
--- /dev/null
+++ b/npc/001-2-34/samantha.txt
@@ -0,0 +1,21 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Artis's Legion of Aemil officier of the training room.
+
+001-2-34,29,27,0 script Samantha NPC_SAMANTHA,{
+ mesn;
+ mesq lg("Look who we have here, did you come for a training session?");
+
+ goto L_Close;
+
+L_Close:
+ close;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-2-35/_import.txt b/npc/001-2-35/_import.txt
new file mode 100644
index 000000000..969d9e1c3
--- /dev/null
+++ b/npc/001-2-35/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-2-35: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-35/_warps.txt",
+"npc/001-2-35/mapflags.txt",
diff --git a/npc/001-2-35/_warps.txt b/npc/001-2-35/_warps.txt
new file mode 100644
index 000000000..d59392226
--- /dev/null
+++ b/npc/001-2-35/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-35: unnamed warps
+001-2-35,23,29,0 warp #001-2-35_23_29 0,0,001-2-32,32,29
diff --git a/npc/001-2-35/mapflags.txt b/npc/001-2-35/mapflags.txt
new file mode 100644
index 000000000..df3ed6a09
--- /dev/null
+++ b/npc/001-2-35/mapflags.txt
@@ -0,0 +1 @@
+001-2-35 mapflag town
diff --git a/npc/001-2-36/_import.txt b/npc/001-2-36/_import.txt
new file mode 100644
index 000000000..222e5a7fc
--- /dev/null
+++ b/npc/001-2-36/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-36: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-36/_warps.txt",
+"npc/001-2-36/mapflags.txt",
+"npc/001-2-36/training_room_npc.txt",
diff --git a/npc/001-2-36/_warps.txt b/npc/001-2-36/_warps.txt
new file mode 100644
index 000000000..9e9c6c701
--- /dev/null
+++ b/npc/001-2-36/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-36: unnamed warps
+001-2-36,37,30,0 warp #001-2-36_37_29 0,0,001-2-34,24,29
diff --git a/npc/001-2-36/mapflags.txt b/npc/001-2-36/mapflags.txt
new file mode 100644
index 000000000..457bc70e5
--- /dev/null
+++ b/npc/001-2-36/mapflags.txt
@@ -0,0 +1 @@
+001-2-36 mapflag town
diff --git a/npc/001-2-36/training_room_npc.txt b/npc/001-2-36/training_room_npc.txt
new file mode 100644
index 000000000..022b5d2ee
--- /dev/null
+++ b/npc/001-2-36/training_room_npc.txt
@@ -0,0 +1,165 @@
+// TrainingRoom
+//
+// Author:
+// jak1
+//
+// Story:
+// Akko Teru
+// Reid
+//
+// Spellchecking & Dialogs
+// Reid
+
+// ~~ VARS ~~
+// $@FightingIsActive
+// 0 = can Warp in Room (non active fight)
+// 1 = can't Warp in Room (active fight)
+
+//TODO adding rand messages like "try hit it harder..." for wave's
+
+
+001-2-36,32,36,0 script FightNPCName NPC_LUCAS,{
+
+ set $@NPCNAME$, "FightNPCName";
+ set $@NPCNEXTNAME$, "Samantha";
+ set $@MOB_ID, 1021;
+ set $@MOB_NAME$, "Dummy";
+ set $@CURRENT_WAVE_LEVEL, 1;
+ set $@MAX_WAVES, 10;
+
+ //Room and Mobspawn Coordinates
+ // TL BR
+ setarray $@MOB_SPAWN_COORDINATES, 24, 34, 31, 41;
+ setarray $@MAP_NAME$, "001-2-36";
+
+ set @roomPlayers, getmapusers($@MAP_NAME$);
+
+ if(@roomPlayers > 1)
+ goto NotAlone;
+
+ if ($@FightingIsActive == 1)
+ {
+ npctalk3 "You are not done now!";
+ end;
+ }
+
+ //call in Warp door if (1 = block)
+ set $@FightingIsActive, 1;
+
+ if (!debug || !is_dev())
+ goto start;
+
+ //can be removed later!
+ menu
+ "get debug vars", debug_it,
+ "reset char var", resetVar,
+ "start training", -;
+
+
+start:
+ if (FIGHT_TRAINING >= 1)
+ goto JobIsDone;
+
+ getmapxy(.@map$, .@x, .@y, 0);
+ if (.@x < 24 || .@x > 32 || .@y < 33 || .@y > 43)
+ {
+ speech S_FIRST_BLANK_LINE, l("Please enter the combat zone on the left.");
+ close;
+ }
+
+ setcells "001-2-36", 33, 35, 33, 38, 1, "fence";
+ initnpctimer;
+ setnpctimer 0;
+ startnpctimer;
+
+ npctalk3 l("Let's begin");
+ end;
+
+
+//cancel all actions, the Player needs to be alone in this Room
+NotAlone:
+ npctalk3 "You dont feel so great with audience!";
+ set $@FightingIsActive, 0;
+ end;
+
+
+//If a Spawned Mob gets Killed
+OnTrainingMobDead:
+ if ($@CURRENT_WAVE_LEVEL == $@MAX_WAVES )
+ goto FinishedTraining;
+
+ set $@CURRENT_WAVE_LEVEL, $@CURRENT_WAVE_LEVEL + 1;
+ setnpctimer 0;
+ startnpctimer;
+ end;
+
+
+SpawnMonster:
+ if ( $@FightingIsActive == 1 )
+ {
+ if ($@CURRENT_WAVE_LEVEL == $@MAX_WAVES)
+ {
+ npctalk "Last Wave!", $@NPCNAME$;
+ }
+ else
+ {
+ npctalk "Wave " + $@CURRENT_WAVE_LEVEL + "!", $@NPCNAME$;
+ }
+
+ areamonster "001-2-36", $@MOB_SPAWN_COORDINATES[0], $@MOB_SPAWN_COORDINATES[1], $@MOB_SPAWN_COORDINATES[2], $@MOB_SPAWN_COORDINATES[3], $@MOB_NAME$, $@MOB_ID, 1, $@NPCNAME$ + "::OnTrainingMobDead";
+ stopnpctimer;
+ setnpctimer 0;
+ }
+ else
+ {
+ set $@CURRENT_WAVE_LEVEL, 0;
+ }
+ stopnpctimer;
+ setnpctimer 0;
+ end;
+
+
+//15 Secounds Waiting (Regeneration for fightRoom)
+OnTimer5000:
+ goto SpawnMonster;
+
+
+FinishedTraining:
+ //... TODO
+
+ npctalk "Con. u finished it...", $@NPCNAME$;
+ stopnpctimer;
+ setnpctimer 0;
+ set $@CURRENT_WAVE_LEVEL, 0;
+ delcells "fence";
+ if (FIGHT_TRAINING >= 1)
+ end;
+ set FIGHT_TRAINING, 1;
+ end;
+
+JobIsDone:
+ mes "Well done, you should talk to \"" + $@NPCNEXTNAME$ + "\"...";
+ close;
+
+
+// ----- DEBUG START ! -----
+
+debug_it:
+ mes "DEBUG INFO";
+ mes "- CharVariable:FIGHT_TRAINING "+ FIGHT_TRAINING;
+ mes "- maxWaves "+ $@MAX_WAVES;
+ mes "- currentWave "+ $@CURRENT_WAVE_LEVEL;
+ mes "- npcName "+ $@NPCNAME$;
+ mes "- mobName "+ $@MOB_NAME$;
+ mes "- mobID "+ $@MOB_ID;
+ close;
+
+resetVar:
+ set FIGHT_TRAINING , 0;
+// ----- DEBUG END ! -----
+
+
+OnInit:
+ end;
+
+}
diff --git a/npc/001-2-37/_import.txt b/npc/001-2-37/_import.txt
new file mode 100644
index 000000000..05315d645
--- /dev/null
+++ b/npc/001-2-37/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-37: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-37/_savepoints.txt",
+"npc/001-2-37/_warps.txt",
+"npc/001-2-37/hammock.txt",
+"npc/001-2-37/mapflags.txt",
diff --git a/npc/001-2-37/_savepoints.txt b/npc/001-2-37/_savepoints.txt
new file mode 100644
index 000000000..2568b51bf
--- /dev/null
+++ b/npc/001-2-37/_savepoints.txt
@@ -0,0 +1,38 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-37: unnamed saves
+001-2-37,25,41,0 script #save_001-2-37_25_41 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-37,35,41,0 script #save_001-2-37_35_41 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-37,35,46,0 script #save_001-2-37_35_46 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-37,25,46,0 script #save_001-2-37_25_46 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-2-37/_warps.txt b/npc/001-2-37/_warps.txt
new file mode 100644
index 000000000..f6997b5f0
--- /dev/null
+++ b/npc/001-2-37/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-37: unnamed warps
+001-2-37,37,28,0 warp #001-2-37_37_28 0,0,001-2-33,24,30
+001-2-37,37,33,0 warp #001-2-37_37_33 0,0,001-2-39,24,33
diff --git a/npc/001-2-37/hammock.txt b/npc/001-2-37/hammock.txt
new file mode 100644
index 000000000..c749217a6
--- /dev/null
+++ b/npc/001-2-37/hammock.txt
@@ -0,0 +1,106 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Animated hammock at the top left level of the Legion of Aemil
+// building of Artis.
+
+001-2-37,26,26,0 script #001-2-37hammock0 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchLeft;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-37,25,28,0 script #001-2-37hammock1 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchLeft;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-37,25,30,0 script #001-2-37hammock2 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchLeft;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-37,25,32,0 script #001-2-37hammock3 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchLeft;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-37,29,26,0 script #001-2-37hammock4 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-37,29,28,0 script #001-2-37hammock5 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-37,29,30,0 script #001-2-37hammock6 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-37,29,32,0 script #001-2-37hammock7 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-37,25,34,0 script #001-2-37hammock8 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-37,26,36,0 script #001-2-37hammock9 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
diff --git a/npc/001-2-37/mapflags.txt b/npc/001-2-37/mapflags.txt
new file mode 100644
index 000000000..c4f939b43
--- /dev/null
+++ b/npc/001-2-37/mapflags.txt
@@ -0,0 +1 @@
+001-2-37 mapflag town
diff --git a/npc/001-2-38/_import.txt b/npc/001-2-38/_import.txt
new file mode 100644
index 000000000..e60aa3f9b
--- /dev/null
+++ b/npc/001-2-38/_import.txt
@@ -0,0 +1,6 @@
+// Map 001-2-38: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-38/_savepoints.txt",
+"npc/001-2-38/_warps.txt",
+"npc/001-2-38/hammock.txt",
+"npc/001-2-38/mapflags.txt",
diff --git a/npc/001-2-38/_savepoints.txt b/npc/001-2-38/_savepoints.txt
new file mode 100644
index 000000000..8b89b8e5f
--- /dev/null
+++ b/npc/001-2-38/_savepoints.txt
@@ -0,0 +1,38 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-38: unnamed saves
+001-2-38,25,41,0 script #save_001-2-38_25_41 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-38,35,41,0 script #save_001-2-38_35_41 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-38,35,46,0 script #save_001-2-38_35_46 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+001-2-38,25,46,0 script #save_001-2-38_25_46 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/001-2-38/_warps.txt b/npc/001-2-38/_warps.txt
new file mode 100644
index 000000000..9139345a8
--- /dev/null
+++ b/npc/001-2-38/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-38: unnamed warps
+001-2-38,23,28,0 warp #001-2-38_23_28 0,0,001-2-33,44,30
+001-2-38,23,33,0 warp #001-2-38_23_33 0,0,001-2-39,44,33
diff --git a/npc/001-2-38/hammock.txt b/npc/001-2-38/hammock.txt
new file mode 100644
index 000000000..2c8938da4
--- /dev/null
+++ b/npc/001-2-38/hammock.txt
@@ -0,0 +1,106 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Animated hammock at the top right level of the Legion of Aemil
+// building of Artis.
+
+001-2-38,31,26,0 script #001-2-38hammock0 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchLeft;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-38,31,28,0 script #001-2-38hammock1 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchLeft;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-38,31,30,0 script #001-2-38hammock2 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchLeft;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-38,31,32,0 script #001-2-38hammoc3 NPC_LEFT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchLeft;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerLeft;
+}
+
+001-2-38,34,26,0 script #001-2-38hammock4 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-38,35,28,0 script #001-2-38hammock5 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-38,35,30,0 script #001-2-38hammock6 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-38,35,32,0 script #001-2-38hammock7 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-38,35,34,0 script #001-2-38hammock8 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
+
+001-2-38,34,36,0 script #001-2-38hammock9 NPC_RIGHT_HAMMOCK,1,0,{
+
+OnTouch: hamTouchRight;
+
+OnUnTouch: hamUnTouch;
+
+OnTimer5440:
+ hamTimerRight;
+}
diff --git a/npc/001-2-38/mapflags.txt b/npc/001-2-38/mapflags.txt
new file mode 100644
index 000000000..8a5c5d4e7
--- /dev/null
+++ b/npc/001-2-38/mapflags.txt
@@ -0,0 +1 @@
+001-2-38 mapflag town
diff --git a/npc/001-2-39/_import.txt b/npc/001-2-39/_import.txt
new file mode 100644
index 000000000..8ceee7679
--- /dev/null
+++ b/npc/001-2-39/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-39: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-39/_warps.txt",
+"npc/001-2-39/mapflags.txt",
+"npc/001-2-39/qanon.txt",
diff --git a/npc/001-2-39/_warps.txt b/npc/001-2-39/_warps.txt
new file mode 100644
index 000000000..527acae5d
--- /dev/null
+++ b/npc/001-2-39/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-39: unnamed warps
+001-2-39,45,33,0 warp #001-2-39_45_33 0,0,001-2-38,24,33
+001-2-39,23,33,0 warp #001-2-39_23_33 0,0,001-2-37,36,33
diff --git a/npc/001-2-39/mapflags.txt b/npc/001-2-39/mapflags.txt
new file mode 100644
index 000000000..5d6887855
--- /dev/null
+++ b/npc/001-2-39/mapflags.txt
@@ -0,0 +1 @@
+001-2-39 mapflag town
diff --git a/npc/001-2-39/qanon.txt b/npc/001-2-39/qanon.txt
new file mode 100644
index 000000000..150362c92
--- /dev/null
+++ b/npc/001-2-39/qanon.txt
@@ -0,0 +1,22 @@
+// Evol scripts.
+// Authors:
+// Alige
+// Reid
+// Description:
+// Artis's Legion of Aemil leader.
+
+001-2-39,34,41,0 script Q'Anon NPC_Q_ANON,{
+ mesn;
+ mesq lg("It's been a while, girl!", "It's been a while, boy!");
+
+ goto L_Close;
+
+L_Close:
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
+
diff --git a/npc/001-2-4/_import.txt b/npc/001-2-4/_import.txt
new file mode 100644
index 000000000..70c629cc6
--- /dev/null
+++ b/npc/001-2-4/_import.txt
@@ -0,0 +1,7 @@
+// Map 001-2-4: Library
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-4/_warps.txt",
+"npc/001-2-4/books.txt",
+"npc/001-2-4/mapflags.txt",
+"npc/001-2-4/robin.txt",
+"npc/001-2-4/terry.txt",
diff --git a/npc/001-2-4/_warps.txt b/npc/001-2-4/_warps.txt
new file mode 100644
index 000000000..dc331e978
--- /dev/null
+++ b/npc/001-2-4/_warps.txt
@@ -0,0 +1,27 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-4: Library warps
+001-2-4,48,41,0 warp #001-2-4_48_41 0,0,001-1,51,81
+001-2-4,57,29,0 warp #001-2-4_57_26 3,0,001-2-6,57,36
+001-2-4,52,27,0 script #001-2-4_52_27_h NPC_HIDDEN,0,0,{
+OnTouch:
+ warp "001-2-5", 28, 37;
+close;
+
+OnUnTouch:
+ doevent "#001-2-4_52_27::OnUnTouch";
+}
+001-2-4,52,27,0 script #001-2-4_52_27 NPC_ARTIS_IN_DOOR,3,3,{
+ close;
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ doorInit;
+}
+
diff --git a/npc/001-2-4/books.txt b/npc/001-2-4/books.txt
new file mode 100644
index 000000000..e09324050
--- /dev/null
+++ b/npc/001-2-4/books.txt
@@ -0,0 +1,102 @@
+// Evol scripts.
+// Author:
+// gumi
+// Tirifto
+// Description:
+// moar books
+
+001-2-4,28,29,0 script #001-2-4-Book1 NPC_NO_SPRITE,{
+
+ doevent "@rules::OnShelfUse";
+ close;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+}
+
+// FIXME: we need a no-sprite npc that is offset 1 tile north
+001-2-4,47,28,0 script #001-2-4-Book2 NPC_NO_SPRITE,{
+
+ function read_book {
+
+ setnpcdialogtitle l(.book_name$);
+
+ narrator S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("To get started with fishing, you'll need two things: a fishing rod and a bait."),
+ l("You just need one fishing rod, although you should take more than one single bait.");
+
+ @menu = 0; // reset for the rif
+
+ do
+ {
+ narrator S_NO_NPC_NAME,
+ l("Please select a chapter:");
+
+ mes "";
+
+ select
+ rif(@menu == 1, "► ") + l("Ch 1 — Fishing apparatus"),
+ rif(@menu == 2, "► ") + l("Ch 2 — Baits"),
+ rif(@menu == 3, "► ") + l("Ch 3 — Location"),
+ rif(@menu == 4, "► ") + l("Ch 4 — Casting"),
+ rif(@menu == 5, "► ") + l("Ch 5 — Reeling");
+
+ switch(@menu)
+ {
+ case 1:
+ narrator S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You'll want your fishing rod to be flexible but solid."),
+ l("Comfortable grip is important especially for newcomers, since they'll be holding it for quite a while.");
+ break;
+ case 2:
+ narrator S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You can use many diverse items to lure fishes."),
+ l("Some people prefer to catch fish using magic, but calling that \"fishing\" would be an insult to this traditional sport."),
+ l("Most common and widely popular in the fish realm are @@ and pieces of @@.",
+ getitemlink(SmallTentacles), getitemlink(Bread)),
+ l("Some types of fish also enjoy @@ quite a bit.",
+ getitemlink(Aquada)),
+ l("Some people, however, prefer to fish with more unorthodox baits, such as @@ or @@.",
+ getitemlink(UrchinMeat), getitemlink(TortugaTongue));
+ break;
+ case 3:
+ narrator S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Find yourself a nice dry spot on a coast where you can easily reach into deep water."),
+ l("Fishing next to shallow water is not going to work well, because fishes seldom go there."),
+ l("You can easily identify fishing spots, small bubbles and fishes are visible from the surface."),
+ l("Don't forget to come as close as possible to these spots!");
+ break;
+ case 4:
+ narrator S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Toss the hook into deep water by clicking on where you want to cast it."),
+ l("Make sure to put on a bait after you click, though!"),
+ l("After that, stay still and be patient, but also alert!");
+ break;
+ case 5:
+ narrator S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("To successfully catch a fish, you need to pull up your hook by clicking it, right after it submerges."),
+ l("Should you be too quick or wait too long, you will most likely fail.");
+ break;
+ }
+ } while (true);
+
+ end;
+ }
+
+OnShelfUse:
+ if (openbookshelf())
+ read_book;
+ bye;
+
+OnUse:
+ if (openbook())
+ read_book;
+ bye;
+
+OnInit:
+ .book_name$ = getitemname(FishingGuideVolI);
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
diff --git a/npc/001-2-4/mapflags.txt b/npc/001-2-4/mapflags.txt
new file mode 100644
index 000000000..1a66f6702
--- /dev/null
+++ b/npc/001-2-4/mapflags.txt
@@ -0,0 +1 @@
+001-2-4 mapflag town
diff --git a/npc/001-2-4/robin.txt b/npc/001-2-4/robin.txt
new file mode 100644
index 000000000..320cf1487
--- /dev/null
+++ b/npc/001-2-4/robin.txt
@@ -0,0 +1,65 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Librarian
+
+001-2-4,27,33,0 script Robin NPC_ROBIN,{
+
+ function need_help
+ {
+ speech S_LAST_NEXT,
+ l("Do you need help with something?");
+
+ switch (select(l("What kinds of books are there here?"),
+ l("Nothing.")))
+ {
+ case 1:
+ closedialog;
+ npctalk3 l("Mostly manuals and tutorials but you won't find out until you open one!");
+ break;
+ case 2:
+ closedialog;
+ npctalk3 l("Good day to you!");
+ }
+ return;
+ }
+
+
+ switch (rand(6))
+ {
+ case 0:
+ npctalkonce l("No matter what people tell you, words and ideas can change the world.");
+ break;
+ case 1:
+ npctalkonce l("In Artis they really do mythologize people when they die.");
+ break;
+ case 2:
+ npctalkonce l("What counts in a book is like so many things, not what is on the outside, but what is on the inside.");
+ break;
+ case 3:
+ npctalkonce l("An explorer left behind some incomplete manuscripts about the people and dangers in the land of Kaizei.");
+ break;
+ case 4:
+ speech S_LAST_NEXT,
+ l("Ow-oh!"),
+ l("Introduce yourself instead of poking me around. I almost fell from the lader, savage...");
+
+ setcamnpc "#001-2-4-Book1";
+
+ speech S_NO_NPC_NAME,
+ l("Go have a look at that shelf to my right, would you?"),
+ l("You clearly need to be more public-spirited.");
+ break;
+ default:
+ need_help;
+ break;
+ }
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-4/terry.txt b/npc/001-2-4/terry.txt
new file mode 100644
index 000000000..937b3ff08
--- /dev/null
+++ b/npc/001-2-4/terry.txt
@@ -0,0 +1,23 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Librarian
+
+001-2-4,51,35,4 script Terry NPC_TERRY,{
+ mesn;
+ mesq l("Hi.");
+ next;
+ mesq l("");
+ goto L_Quit;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ .dir = 2;
+ end;
+
+L_Quit:
+ .dir = 2;
+ close;
+}
diff --git a/npc/001-2-40/_import.txt b/npc/001-2-40/_import.txt
new file mode 100644
index 000000000..a7c7abb85
--- /dev/null
+++ b/npc/001-2-40/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-40: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-40/_warps.txt",
+"npc/001-2-40/mapflags.txt",
+"npc/001-2-40/trozz.txt",
diff --git a/npc/001-2-40/_warps.txt b/npc/001-2-40/_warps.txt
new file mode 100644
index 000000000..83550f10f
--- /dev/null
+++ b/npc/001-2-40/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-40: unnamed warps
+001-2-40,45,44,0 warp #001-2-40_45_44 2,0,001-2-33,43,39
+001-2-40,27,47,0 warp #001-2-40_27_44 2,0,001-2-33,25,39
diff --git a/npc/001-2-40/mapflags.txt b/npc/001-2-40/mapflags.txt
new file mode 100644
index 000000000..0c9303e82
--- /dev/null
+++ b/npc/001-2-40/mapflags.txt
@@ -0,0 +1 @@
+001-2-40 mapflag town
diff --git a/npc/001-2-40/trozz.txt b/npc/001-2-40/trozz.txt
new file mode 100644
index 000000000..df76c26f5
--- /dev/null
+++ b/npc/001-2-40/trozz.txt
@@ -0,0 +1,21 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Chief of the Legion of Aemil of the city of Artis.
+
+001-2-40,36,46,0 script Trozz#001-2-40 NPC_HUMAN_MALE_CHIEF_ARTIS_LEGION,{
+ mesn;
+ mesq l("Hi.");
+
+ goto L_Close;
+
+L_Close:
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 4;
+ end;
+}
+
diff --git a/npc/001-2-41/_import.txt b/npc/001-2-41/_import.txt
new file mode 100644
index 000000000..a8eee7261
--- /dev/null
+++ b/npc/001-2-41/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-41: unnamed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-41/_warps.txt",
+"npc/001-2-41/edouard.txt",
+"npc/001-2-41/mapflags.txt",
diff --git a/npc/001-2-41/_warps.txt b/npc/001-2-41/_warps.txt
new file mode 100644
index 000000000..7a10c00d4
--- /dev/null
+++ b/npc/001-2-41/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-41: unnamed warps
+001-2-41,24,32,0 warp #001-2-41_24_32 0,0,001-2-31,35,32
diff --git a/npc/001-2-41/edouard.txt b/npc/001-2-41/edouard.txt
new file mode 100644
index 000000000..f93d2042a
--- /dev/null
+++ b/npc/001-2-41/edouard.txt
@@ -0,0 +1,169 @@
+// Evol scripts.
+// Authors:
+// Reid
+// Travolta
+// Description:
+// Barber of Aemil
+
+function script EdouardCheckChair {
+
+ getmapxy(.@map$, .@x, .@y, UNITTYPE_PC);
+
+ if ((.@map$ != getarg(0)) || (.@x != getarg(1)) || (.@y != getarg(2)))
+ {
+ doevent "Edouard#001-2-41::OnWrongPlace";
+ }
+ else if (!issit())
+ {
+ doevent "Edouard#001-2-41::OnNotSit";
+ }
+ else
+ {
+ doevent "Edouard#001-2-41::OnChair";
+ }
+
+ close;
+}
+
+001-2-41,29,24,0 script Chair#Chair1-001-2-41 NPC_NO_SPRITE,{
+
+ EdouardCheckChair .map$, .x, .y;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-2-41,31,24,0 script Chair#Chair2-001-2-41 NPC_NO_SPRITE,{
+
+ EdouardCheckChair .map$, .x, .y;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-2-41,35,27,0 script Chair#Chair3-001-2-41 NPC_NO_SPRITE,{
+
+ EdouardCheckChair .map$, .x, .y;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-2-41,35,29,0 script Chair#Chair4-001-2-41 NPC_NO_SPRITE,{
+
+ EdouardCheckChair .map$, .x, .y;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-2-41,35,35,0 script Chair#Chair5-001-2-41 NPC_NO_SPRITE,{
+
+ EdouardCheckChair .map$, .x, .y;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-2-41,35,37,0 script Chair#Chair6-001-2-41 NPC_NO_SPRITE,{
+
+ EdouardCheckChair .map$, .x, .y;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-2-41,30,29,0 script Edouard#001-2-41 NPC_EDOUARD,{
+
+ function tellStory {
+ if (Edouard_StoryTold != 0)
+ {
+ mes "";
+ mesn;
+ }
+ speech S_LAST_NEXT | S_NO_NPC_NAME,
+ l("I am new in this town, just like you."),
+ l("I came here, looking for a better life."),
+ l("And so far, the Merchant Guild helped me find this appartment so I can't complain!"),
+ l("Anyway."),
+ l("I'm a barber, you see. I can change your hairstyle or hair color to your current taste.");
+
+ Edouard_StoryTold = 1;
+
+ return;
+ }
+
+OnWrongPlace:
+ npctalkonce("Sit on the chair, I will come in a second!");
+ close;
+
+OnNotSit:
+ npctalkonce("Please sit.");
+ close;
+
+OnChair:
+ speech S_LAST_NEXT,
+ lg("Hello, young lady.", "Hello, young man.");
+
+ if (Edouard_StoryTold == 0)
+ {
+ tellStory;
+ }
+
+ speech S_LAST_NEXT | S_NO_NPC_NAME,
+ l("What would you like me to do?");
+
+ do
+ {
+ select
+ l("What is my current hairstyle and hair color?"),
+ l("I'd like to get a different style."),
+ l("Can you do something with my color?"),
+ l("What's your story again?"),
+ l("I'm fine for now, thank you.");
+
+ switch (@menu)
+ {
+ case 1:
+ BarberSayStyle 3;
+ break;
+ case 2:
+ BarberChangeStyle;
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Enjoy your new style.");
+ l("Anything else?");
+ break;
+ case 3:
+ BarberChangeColor;
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("I hope you like this color.");
+ l("Anything else?");
+ break;
+ case 4:
+ tellStory;
+ break;
+ case 5:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Feel free to come visit me another time.");
+
+ goodbye;
+ }
+ } while (1);
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-41/mapflags.txt b/npc/001-2-41/mapflags.txt
new file mode 100644
index 000000000..eb1b712b6
--- /dev/null
+++ b/npc/001-2-41/mapflags.txt
@@ -0,0 +1 @@
+001-2-41 mapflag town
diff --git a/npc/001-2-42/_import.txt b/npc/001-2-42/_import.txt
new file mode 100644
index 000000000..1afffd482
--- /dev/null
+++ b/npc/001-2-42/_import.txt
@@ -0,0 +1,3 @@
+// Map 001-2-42: Docks Warehouse Second Level
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-42/_warps.txt",
diff --git a/npc/001-2-42/_warps.txt b/npc/001-2-42/_warps.txt
new file mode 100644
index 000000000..508aae1b1
--- /dev/null
+++ b/npc/001-2-42/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-42: Docks Warehouse Second Level warps
+001-2-42,39,38,0 warp #001-2-42_39_37 2,0,001-2-18,39,28
diff --git a/npc/001-2-5/_import.txt b/npc/001-2-5/_import.txt
new file mode 100644
index 000000000..2e399b365
--- /dev/null
+++ b/npc/001-2-5/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-5: Warehouse
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-5/_warps.txt",
+"npc/001-2-5/books.txt",
+"npc/001-2-5/mapflags.txt",
diff --git a/npc/001-2-5/_warps.txt b/npc/001-2-5/_warps.txt
new file mode 100644
index 000000000..7d5431439
--- /dev/null
+++ b/npc/001-2-5/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-5: Warehouse warps
+001-2-5,28,38,0 warp #001-2-5_28_38 0,0,001-2-4,52,29
diff --git a/npc/001-2-5/books.txt b/npc/001-2-5/books.txt
new file mode 100644
index 000000000..c0d05df21
--- /dev/null
+++ b/npc/001-2-5/books.txt
@@ -0,0 +1,34 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Gasaron
+
+001-2-5,30,32,0 script #001-2-5-Book1 NPC_NO_SPRITE,{
+
+ function read_book {
+ narrator S_FIRST_BLANK_LINE,
+ l("There are two kinds of dialogue, the ones with regular citizens, and the ones with other adventurers."),
+ l("When you go near villagers, you can see a speech bubble above them, you can then talk to them by pressing the [T] key."),
+ l("You can select a specific person with the [N] key, and then, press the [T] key when you are surrounded by more than one person."),
+ l("You can also simply talk to any citizen around you by clicking on them."),
+ l("Nevertheless, you can talk with another adventurer by pressing the [Enter] key and then type what you want to say!"),
+ l("If you want to say something to a specific player, you can type \"/query Playername\" or \"/whisper Playername message\", this will create a new tab on your chat window.");
+ }
+
+OnShelfUse:
+ if (openbookshelf())
+ read_book;
+ close;
+
+OnUse:
+ if (openbook())
+ read_book;
+ close;
+
+OnInit:
+ .book_name$ = "Communication Theory";
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
diff --git a/npc/001-2-5/mapflags.txt b/npc/001-2-5/mapflags.txt
new file mode 100644
index 000000000..973aa8620
--- /dev/null
+++ b/npc/001-2-5/mapflags.txt
@@ -0,0 +1 @@
+001-2-5 mapflag town
diff --git a/npc/001-2-6/_import.txt b/npc/001-2-6/_import.txt
new file mode 100644
index 000000000..cc06496d0
--- /dev/null
+++ b/npc/001-2-6/_import.txt
@@ -0,0 +1,8 @@
+// Map 001-2-6: First Floor
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-6/_warps.txt",
+"npc/001-2-6/books.txt",
+"npc/001-2-6/christopher.txt",
+"npc/001-2-6/dolfina.txt",
+"npc/001-2-6/leonard.txt",
+"npc/001-2-6/mapflags.txt",
diff --git a/npc/001-2-6/_warps.txt b/npc/001-2-6/_warps.txt
new file mode 100644
index 000000000..e778bf331
--- /dev/null
+++ b/npc/001-2-6/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-6: First Floor warps
+001-2-6,57,38,0 warp #001-2-6_57_38 3,0,001-2-4,57,28
diff --git a/npc/001-2-6/books.txt b/npc/001-2-6/books.txt
new file mode 100644
index 000000000..53091bdf0
--- /dev/null
+++ b/npc/001-2-6/books.txt
@@ -0,0 +1,167 @@
+// Evol scripts.
+// Authors:
+// Reid
+// WildX
+// Description:
+// Aemil
+
+001-2-6,39,41,0 script #001-2-6-Book1 NPC_NO_SPRITE,{
+
+ function read_book {
+ mes "";
+ mes col("Master Piou sat on a tree,", 9);
+ mes col("Holding a cheese in his beak.", 9);
+ mes col("Master Fluffy was attracted by the odour,", 9);
+ mes col("And tried to attract him thus.", 9);
+ next;
+ mes col("\"Mister Piou, good day to you.", 9);
+ mes col("You are a handsome and good looking bird!", 9);
+ mes col("In truth, if your song is as beautiful as your plumage,", 9);
+ mes col("You are the Phoenix of this forest.\"", 9);
+ next;
+ mes col("Hearing these words the Piou felt great joy,", 9);
+ mes col("And to demonstrate his beautiful voice,", 9);
+ mes col("He opened his mouth wide and let drop his prey.", 9);
+ mes col("The Fluffy seized it and said:", 9);
+ next;
+ mes col("\"My good Sir,", 9);
+ mes col("Know that every flatterer,", 9);
+ mes col("Lives at the expense of those who take him seriously:", 9);
+ mes col("This is a lesson that is worth a cheese no doubt.\"", 9);
+ next;
+ mes col("The Piou, embarrassed and confused,", 9);
+ mes col("Swore, though somewhat later, that he would never be ", 9);
+ mes col("tricked thus again.", 9);
+ next;
+ mes col("-- " + l("Aesop"), 9);
+ }
+
+OnShelfUse:
+ if (openbookshelf())
+ read_book;
+ close;
+
+OnUse:
+ if (openbook())
+ read_book;
+ close;
+
+OnInit:
+ .book_name$ = "The Piou and The Fluffy";
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-2-6,48,41,0 script #001-2-6-Book2 NPC_NO_SPRITE,{
+
+ function read_book {
+ mes "";
+ mes col("Poem is making the words dance", 9);
+ mes col("Words become music and glance", 9);
+ mes col("Over lovers under a starry night", 9);
+ mes col("Whose eyes listen under Moonlight", 9);
+ next;
+ mes col("No matter the grammar", 9);
+ mes col("If words beat in rhythm", 9);
+ mes col("Find an order with them", 9);
+ mes col("As on anvil strikes the hammer", 9);
+ next;
+ mes col("No matter the spelling", 9);
+ mes col("Just say something sparkling", 9);
+ mes col("If not, how could CrazyKatiektch", 9);
+ mes col("Say her love to glamourous Gliktch?", 9);
+ next;
+ mes col("True be or not true be", 9);
+ mes col("That's not the question", 9);
+ mes col("And rhyming is not too", 9);
+ mes col("If you don't like to", 9);
+ mes col("Share your mind is your mission", 9);
+ mes col("Whatever inside can be", 9);
+ next;
+ mes col("Don't be shy, you are nice", 9);
+ mes col("From your mind, break the ice", 9);
+ mes col("Whatever your idea", 9);
+ mes col("It's the good one and, ahem!", 9);
+ mes col("That makes everybody", 9);
+ mes col("Able to write a poem", 9);
+ next;
+ mes col("-- " + l("Nard"), 9);
+ }
+
+OnShelfUse:
+ if (openbookshelf())
+ read_book;
+ close;
+
+OnUse:
+ if (openbook())
+ read_book;
+ close;
+
+OnInit:
+ .book_name$ = "Poem about Poems";
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-2-6,43,39,0 script #001-2-6-Book3 NPC_NO_SPRITE,{
+
+ function read_book {
+ mes "";
+ mes col("Hush now and hear the chorus of the woods", 9);
+ mes col("Bent trees whistling with the beat of the drum", 9);
+ mes col("With no choir master nor voice to be sung", 9);
+ mes col("The music of the trees floats through the breeze", 9);
+ mes col("Sleep well my angel but don't follow along", 9);
+ mes col("Because the voices of death sing a sweet song", 9);
+ next;
+ mes col("-- " + l("Princess Slayer"), 9);
+ }
+
+OnShelfUse:
+ if (openbookshelf())
+ read_book;
+ close;
+
+OnUse:
+ if (openbook())
+ read_book;
+ close;
+
+OnInit:
+ .book_name$ = "Chorus of the Woods";
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
+
+001-2-6,54,28,0 script #001-2-6-Book4 NPC_NO_SPRITE,{
+
+ function read_book {
+ narrator S_FIRST_BLANK_LINE,
+ l("Aemil was once a magnificent land unknown to us all."),
+ l("Before the end of the Mana War, a band of adventurers formed in the Ancean region of Argaes from those who had lost their homes and families."),
+ l("They sailed from Hurnscald to Tulimshar and then Nivalis, the last permanent settlements of humans."),
+ l("There, they gathered merchants and warriors to join them in a journey to find a new land on which to live."),
+ l("The group found the support of Tulimshar's merchant lords and was given ships to sail east."),
+ l("They sailed past the Clear Sea and towards the Long Ocean which nobody had explored before."),
+ l("The newly created Fleet of Ancea travelled so far that they were never heard from again."),
+ l("Their leaders then came to the conclusion that an alliance was the only way they could survive."),
+ l("They eventually found a new land after much hardship and named it Aurora, after its beautiful sunrise."),
+ l("A great city, eventually to become larger than the cities of Ancea, rose on the coast of Aemil. This city was named Esperia."),
+ l("However..."),
+ l("The end of the story got erased, probably because of the sea water. Some pages are still missing. Thus much is lost to time, including the author's name.");
+ }
+
+OnUse:
+ if (openoldbook())
+ read_book;
+ close;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 1;
+ end;
+}
diff --git a/npc/001-2-6/christopher.txt b/npc/001-2-6/christopher.txt
new file mode 100644
index 000000000..1bef67866
--- /dev/null
+++ b/npc/001-2-6/christopher.txt
@@ -0,0 +1,69 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Librarian
+
+001-2-6,57,46,0 script Christopher NPC_CHRISTOPHER,{
+ function ghost_in_the_library
+ {
+ narrator S_LAST_NEXT,
+ l("Christopher is surrounded by the sunlight from the window.");
+
+ speech
+ l("To be a legend, you've either got to be dead or excessively old!"),
+ l("I think that I am now both..."),
+ l("I mean, I am very tired to move all of these books!");
+
+ return;
+ }
+
+ function need_help
+ {
+ speech S_LAST_NEXT,
+ l("Do you need help with something?");
+
+ switch (select(l("What kinds of books are there here?"),
+ l("You seem a bit tired sir."),
+ l("Nothing.")))
+ {
+ case 1:
+ npctalk3 l("You can find novels and poems on this floor.");
+ break;
+ case 2:
+ mes "";
+ ghost_in_the_library();
+ break;
+ case 3:
+ npctalk3 l("I love peace and quiet, that's a good choice.");
+ }
+ return;
+ }
+
+ function not_so_loud
+ {
+ npctalkonce l("This floor is reserved for quiet reading, don't speak too loud.");
+
+ return;
+ }
+
+ switch (rand(3))
+ {
+ case 0:
+ ghost_in_the_library();
+ break;
+ case 1:
+ need_help();
+ break;
+ case 2:
+ not_so_loud();
+ break;
+ }
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-6/dolfina.txt b/npc/001-2-6/dolfina.txt
new file mode 100644
index 000000000..8d9c1a2c4
--- /dev/null
+++ b/npc/001-2-6/dolfina.txt
@@ -0,0 +1,21 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Aemil
+
+001-2-6,31,44,0 script Dolfina NPC_ELVEN_FEMALE_READING,{
+ mesn;
+ mesq l("Stop disturbing me, I already re-read that part twice because of you!");
+
+ goto L_Close;
+
+L_Close:
+ close;
+
+OnInit:
+ .sex = G_FEMALE;
+ .distance = 2;
+ end;
+}
+
diff --git a/npc/001-2-6/leonard.txt b/npc/001-2-6/leonard.txt
new file mode 100644
index 000000000..7b238c1a0
--- /dev/null
+++ b/npc/001-2-6/leonard.txt
@@ -0,0 +1,89 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Librarian
+
+001-2-6,52,28,0 script Leonard NPC_LEONARD,{
+
+ function esperia_city
+ {
+ speech S_FIRST_BLANK_LINE,
+ l("You have put your finger on it, I am not."),
+ l("I grew up and lived a good while in Esperia, the capital city."),
+ l("This place is surrounded by two very important elements: academia and the arts. I was surrounded by theater, music, dance, museums..."),
+ l("I had a great childhood in Esperia!"),
+ l("It was wonderful.");
+
+ emotion E_HAPPY;
+
+ return;
+ }
+
+ function need_help
+ {
+ speech S_LAST_NEXT,
+ l("Do you need help with something?");
+
+ switch (select(l("What kinds of books are there here?"),
+ l("Are you a native from Artis?"),
+ l("Nothing.")))
+ {
+ case 1:
+ closedialog;
+ npctalk3 l("You can find novels and poems on this floor.");
+ break;
+ case 2:
+ esperia_city();
+ break;
+ case 3:
+ closedialog;
+ npctalk3 l("Good day to you!");
+ }
+ return;
+ }
+
+ function not_so_loud
+ {
+ npctalkonce l("This floor is reserved for quiet reading, don't speak too loud.");
+
+ return;
+ }
+
+ function miracle
+ {
+ npctalkonce l("The miracle is this: the more we share, the more we have.");
+
+ return;
+ }
+
+ function logic_wisdom
+ {
+ npctalkonce l("Logic is the beginning of wisdom, not the end.");
+
+ return;
+ }
+
+ switch (rand(4))
+ {
+ case 0:
+ logic_wisdom();
+ break;
+ case 1:
+ miracle();
+ break;
+ case 2:
+ not_so_loud();
+ break;
+ case 3:
+ need_help();
+ break;
+ }
+
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 2;
+ end;
+}
diff --git a/npc/001-2-6/mapflags.txt b/npc/001-2-6/mapflags.txt
new file mode 100644
index 000000000..f5ba3e951
--- /dev/null
+++ b/npc/001-2-6/mapflags.txt
@@ -0,0 +1 @@
+001-2-6 mapflag town
diff --git a/npc/001-2-7/_import.txt b/npc/001-2-7/_import.txt
new file mode 100644
index 000000000..6d588bf81
--- /dev/null
+++ b/npc/001-2-7/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-2-7: City Hall
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-7/_warps.txt",
+"npc/001-2-7/mapflags.txt",
diff --git a/npc/001-2-7/_warps.txt b/npc/001-2-7/_warps.txt
new file mode 100644
index 000000000..d59fa937b
--- /dev/null
+++ b/npc/001-2-7/_warps.txt
@@ -0,0 +1,5 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-7: City Hall warps
+001-2-7,36,46,0 warp #001-2-7_36_46 0,0,001-1,89,66
+001-2-7,46,31,0 warp #001-2-7_46_31 0,0,001-2-9,25,41
+001-2-7,26,31,0 warp #001-2-7_26_31 0,0,001-2-8,45,41
diff --git a/npc/001-2-7/mapflags.txt b/npc/001-2-7/mapflags.txt
new file mode 100644
index 000000000..69598b890
--- /dev/null
+++ b/npc/001-2-7/mapflags.txt
@@ -0,0 +1 @@
+001-2-7 mapflag town
diff --git a/npc/001-2-8/_import.txt b/npc/001-2-8/_import.txt
new file mode 100644
index 000000000..93b064fe2
--- /dev/null
+++ b/npc/001-2-8/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-2-8: Left Wing
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-8/_warps.txt",
+"npc/001-2-8/mapflags.txt",
diff --git a/npc/001-2-8/_warps.txt b/npc/001-2-8/_warps.txt
new file mode 100644
index 000000000..43412f720
--- /dev/null
+++ b/npc/001-2-8/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-8: Left Wing warps
+001-2-8,46,41,0 warp #001-2-8_46_41 0,0,001-2-7,27,31
diff --git a/npc/001-2-8/mapflags.txt b/npc/001-2-8/mapflags.txt
new file mode 100644
index 000000000..3def9ed24
--- /dev/null
+++ b/npc/001-2-8/mapflags.txt
@@ -0,0 +1 @@
+001-2-8 mapflag town
diff --git a/npc/001-2-9/_import.txt b/npc/001-2-9/_import.txt
new file mode 100644
index 000000000..ebac336c1
--- /dev/null
+++ b/npc/001-2-9/_import.txt
@@ -0,0 +1,5 @@
+// Map 001-2-9: Right Wing
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-2-9/_warps.txt",
+"npc/001-2-9/janus.txt",
+"npc/001-2-9/mapflags.txt",
diff --git a/npc/001-2-9/_warps.txt b/npc/001-2-9/_warps.txt
new file mode 100644
index 000000000..b4d3c594d
--- /dev/null
+++ b/npc/001-2-9/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-2-9: Right Wing warps
+001-2-9,24,41,0 warp #001-2-9_24_41 0,0,001-2-7,45,31
diff --git a/npc/001-2-9/janus.txt b/npc/001-2-9/janus.txt
new file mode 100644
index 000000000..a652a7c5e
--- /dev/null
+++ b/npc/001-2-9/janus.txt
@@ -0,0 +1,170 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Party NPC
+// Variable:
+// General_Janus
+// Values:
+// 0 Default.
+// 1 Basic information given.
+// 2 Party creation enabled.
+// 3 Guild certificate given.
+
+001-2-9,30,28,0 script Janus NPC_JANUS,{
+
+ function create_party {
+ .@party_price = 1000;
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Creating a party has some advantages, it's a pretty good choice!"),
+ l("I remember when I created my first party, we were amazed to share some experience with a small group of adventurer..."),
+ l("Oh! And our party chat was really entertaining, I do highly recommend you to share this fun as well."),
+ lg("The cost to create a party is @@ E, are you interested?",
+ "The cost to create a party is @@ E, are you interested?", .@party_price);
+
+ if (askyesno() == 1)
+ {
+ if (Zeny < .@party_price)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("You don't have enough money, bring @@ E.", .@party_price);
+ }
+ else
+ {
+ Zeny = Zeny - .@party_price;
+ setq General_Janus, 2;
+ skill NV_BASIC, 7, 0;
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("Awesome, come back if you ever want to create a larger group!");
+ }
+ }
+ }
+
+ function create_guild {
+ .@guild_price = 35000;
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Oh oh... I see, your party became so big that you want to create an even larger structure?"),
+ l("Or do you want to keep your friendships and adventures in different groups?"),
+ l("Anyway, the guild creation is perfect for both!"),
+ l("You can keep your current party as it is, while leading or being part of a guild in order to talk and share different items with all of its members!"),
+ l("The @@ is a one time item, you can use it as many times as you want, but you can only have one!", getitemlink(GuildCertification)),
+ lg("The cost to create a guild is @@ E, are you interested?",
+ "The cost to create a guild is @@ E, are you interested?", .@guild_price);
+
+ if (askyesno() == 1)
+ {
+ if (Zeny < .@guild_price)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("You don't have enough money, bring @@ E.", .@guild_price);
+ }
+ else
+ {
+ inventoryplace GuildCertification, 1;
+ Zeny = Zeny - .@guild_price;
+ setq General_Janus, 3;
+ getitem GuildCertification, 1;
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("Enjoy the fraternity and excitement of your future guild!");
+ }
+ }
+ }
+
+ function explain_service {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You are on the human resource wing of the Town Hall."),
+ l("We offer party and guild certifications and we can also teach you how to use some basic communication skills."),
+ l("Do you know how to speak with people around you?");
+
+ if (askyesno() == 2)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You lack some very basic skills...");
+
+ if (compareandsetq(General_Janus, 0, 1))
+ {
+ speech S_LAST_NEXT | S_NO_NPC_NAME,
+ l("This book contains everything you should know about it, take it!");
+
+ inventoryplace CommunicationTheory, 1;
+ getitem CommunicationTheory, 1;
+ }
+ else
+ {
+ speech S_LAST_NEXT | S_NO_NPC_NAME,
+ l("You can read the book that I gave you earlier at the library if you lost it.");
+ }
+ }
+ else
+ {
+ if (compareandsetq(General_Janus, 0, 1))
+ {
+ speech S_LAST_NEXT | S_NO_NPC_NAME,
+ l("Anyway."),
+ l("This book contains everything you should know about it, take it!");
+
+ inventoryplace CommunicationTheory, 1;
+ getitem CommunicationTheory, 1;
+ }
+
+ }
+
+ return;
+ }
+
+ function janus_is_not_ianus {
+ speech S_FIRST_BLANK_LINE,
+ l("Janus!");
+ emotion E_UPSET;
+ next;
+
+ speech S_LAST_NEXT | S_NO_NPC_NAME,
+ l("Ianus is from the Legion of Aemil, don't compare me to this brigand.");
+
+ return;
+ }
+
+ speech S_LAST_NEXT,
+ lg("Welcome miss.", "Good day sir.");
+
+ do
+ {
+ // Beta users by-pass check.
+ if (getskilllv(NV_BASIC) > 6 && getq(General_Janus) == 1)
+ {
+ setq General_Janus, 2;
+ }
+
+ select
+ rif(getq(General_Janus) == 1, l("I would like to create a party.")),
+ rif(getq(General_Janus) == 2, l("I would like to create a guild.")),
+ l("What service do you offer?"),
+ l("Your name is Ianus or Janus?"),
+ menuaction(l("Quit"));
+
+ switch (@menu)
+ {
+ case 1:
+ create_party;
+ break;
+ case 2:
+ create_guild;
+ break;
+ case 3:
+ explain_service;
+ break;
+ case 4:
+ janus_is_not_ianus;
+ break;
+ }
+ } while (@menu != 5);
+
+ closedialog;
+ goodbye;
+ close;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ end;
+}
diff --git a/npc/001-2-9/mapflags.txt b/npc/001-2-9/mapflags.txt
new file mode 100644
index 000000000..47b7f630b
--- /dev/null
+++ b/npc/001-2-9/mapflags.txt
@@ -0,0 +1 @@
+001-2-9 mapflag town
diff --git a/npc/001-3-0/_import.txt b/npc/001-3-0/_import.txt
new file mode 100644
index 000000000..320f28ce4
--- /dev/null
+++ b/npc/001-3-0/_import.txt
@@ -0,0 +1,4 @@
+// Map 001-3-0: Sewer
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-3-0/_mobs.txt",
+"npc/001-3-0/_warps.txt",
diff --git a/npc/001-3-0/_mobs.txt b/npc/001-3-0/_mobs.txt
new file mode 100644
index 000000000..31c8266fe
--- /dev/null
+++ b/npc/001-3-0/_mobs.txt
@@ -0,0 +1,17 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-3-0: Sewer mobs
+001-3-0,175,32,2,2 monster Ratto 1005,2,60000,30000
+001-3-0,201,54,2,2 monster Ratto 1005,3,25000,10000
+001-3-0,151,97,18,1 monster Ratto 1005,3,40000,15000
+001-3-0,146,121,3,2 monster Ratto 1005,2,50000,25000
+001-3-0,101,111,8,3 monster Ratto 1005,4,30000,15000
+001-3-0,145,68,2,2 monster Ratto 1005,2,60000,30000
+001-3-0,146,28,2,1 monster Ratto 1005,2,60000,30000
+001-3-0,90,65,3,3 monster Ratto 1005,3,35000,15000
+001-3-0,56,50,8,4 monster Ratto 1005,4,35000,15000
+001-3-0,42,102,3,3 monster Ratto 1005,3,40000,20000
+001-3-0,145,64,1,5 monster Blub 1008,2,35000,80000
+001-3-0,162,45,1,3 monster Little Blub 1007,4,10000,20000
+001-3-0,129,88,2,2 monster Blub 1008,2,35000,80000
+001-3-0,100,38,2,2 monster Little Blub 1007,4,10000,20000
+001-3-0,171,45,0,2 monster Little Blub 1007,4,10000,20000
diff --git a/npc/001-3-0/_warps.txt b/npc/001-3-0/_warps.txt
new file mode 100644
index 000000000..a2d4e9e23
--- /dev/null
+++ b/npc/001-3-0/_warps.txt
@@ -0,0 +1,8 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-3-0: Sewer warps
+001-3-0,196,35,0 warp #001-3-0_196_35 0,0,001-1,197,35
+001-3-0,172,41,0 warp #001-3-0_172_41 0,0,001-3-1,34,58
+001-3-0,162,40,0 warp #001-3-0_162_40 0,0,001-3-1,23,57
+001-3-0,198,59,0 warp #001-3-0_198_59 0,0,001-1,199,61
+001-3-0,152,55,0 warp #001-3-0_152_55 0,0,001-1,152,51
+001-3-0,85,130,0 warp #001-3-0_85_130 0,0,001-1,86,130
diff --git a/npc/001-3-1/_import.txt b/npc/001-3-1/_import.txt
new file mode 100644
index 000000000..6511aab37
--- /dev/null
+++ b/npc/001-3-1/_import.txt
@@ -0,0 +1,3 @@
+// Map 001-3-1: Rivercave
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/001-3-1/_warps.txt",
diff --git a/npc/001-3-1/_warps.txt b/npc/001-3-1/_warps.txt
new file mode 100644
index 000000000..f0c3d747b
--- /dev/null
+++ b/npc/001-3-1/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 001-3-1: Rivercave warps
+001-3-1,24,58,0 warp #001-3-1_24_58 1,0,001-3-0,162,41
+001-3-1,35,59,0 warp #001-3-1_35_59 1,0,001-3-0,172,42
diff --git a/npc/008-1/_import.txt b/npc/008-1/_import.txt
new file mode 100644
index 000000000..38da1dae2
--- /dev/null
+++ b/npc/008-1/_import.txt
@@ -0,0 +1,7 @@
+// Map 008-1: Hurnscald
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-1/_mobs.txt",
+"npc/008-1/_warps.txt",
+"npc/008-1/doors.txt",
+"npc/008-1/mapflags.txt",
+"npc/008-1/wateranimation.txt",
diff --git a/npc/008-1/_mobs.txt b/npc/008-1/_mobs.txt
new file mode 100644
index 000000000..e8835c097
--- /dev/null
+++ b/npc/008-1/_mobs.txt
@@ -0,0 +1,15 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-1: Hurnscald mobs
+008-1,99,39,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,100,42,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,102,40,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,105,41,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,101,44,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,104,43,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,109,40,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,108,42,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,106,44,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,109,44,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,111,42,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,112,44,0,0 monster Manana Tree 1017,1,420000,240000
+008-1,112,39,0,0 monster Manana Tree 1017,1,420000,240000
diff --git a/npc/008-1/_warps.txt b/npc/008-1/_warps.txt
new file mode 100644
index 000000000..44b0db660
--- /dev/null
+++ b/npc/008-1/_warps.txt
@@ -0,0 +1,13 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-1: Hurnscald warps
+008-1,105,76,0 warp #008-1_105_76 0,0,008-2-0,26,23
+008-1,102,79,0 warp #008-1_102_79 0,0,008-2-0,23,34
+008-1,88,71,0 warp #008-1_88_71 0,0,008-2-1,33,42
+008-1,90,66,0 warp #008-1_90_66 0,0,008-2-1,38,27
+008-1,65,55,0 warp #008-1_65_55 0,0,008-2-2,28,33
+008-1,89,58,0 warp #008-1_89_58 0,0,008-2-6,27,32
+008-1,101,55,0 warp #008-1_101_55 0,0,008-2-7,36,28
+008-1,121,71,0 warp #008-1_121_71 1,0,008-2-8,36,38
+008-1,72,68,0 warp #008-1_72_68 0,0,008-2-9,30,34
+008-1,102,69,0 warp #008-1_102_69 0,0,008-2-10,37,33
+008-1,110,56,0 warp #008-1_110_56 0,0,008-2-12,30,31
diff --git a/npc/008-1/confused-tree.txt b/npc/008-1/confused-tree.txt
new file mode 100644
index 000000000..2d5a53631
--- /dev/null
+++ b/npc/008-1/confused-tree.txt
@@ -0,0 +1,957 @@
+// Evol scripts.
+// Author:
+// gumi
+// Based on CrazyTree, originally made by:
+// gumi
+// pclouds
+// veryape
+// wushin
+// Description:
+// emulated confused tree prototype
+
+// ~t lowercase hot word regex
+
+008-1,84,63,0 script Confused Tree NPC_CONFUSED_TREE,14,14,{
+
+ function tree_panel {
+ if (is_trusted() == false && #Tree_Trusted == false)
+ {
+ narrator(l("You see a tree."));
+ if (getq(HurnscaldQuests_Inspector) == 2)
+ {
+ select(
+ l("Have you seen anything strange lately?"),
+ l("Do you know anything about the recent robberies?"));
+
+ narrator(S_FIRST_BLANK_LINE,
+ l("..."),
+ l("It doesn't reply."));
+ }
+ close;
+ }
+
+ function clear_db {
+ clear();
+ mes(l("##BWARNING:##b you are about to permanently empty the quote database."));
+ next();
+ mes(l("Do you want to continue?"));
+
+ select(
+ l("Abort!"),
+ l("Empty the quote DB"));
+
+ if (@menu == 2)
+ {
+ .@sentence$ = "I am an idiot";
+ mes(l("Please write the following sentence:"));
+ mes("");
+ mesf(" ##B%s.", .@sentence$);
+ input(.@confirm$);
+
+ if (!startswith(strtoupper(.@confirm$), strtoupper(.@sentence$))) {
+ mes(l("Invalid!"));
+ close;
+ }
+
+ query_sql("TRUNCATE TABLE tree_quotes;");
+ mes(l("Database erased."));
+ next();
+ }
+
+ return;
+ }
+
+ function list_commands {
+ clear();
+ mes(l("To grab a quote:"));
+ mes(col(" ~grab ##Bplayer name##b", 7));
+ next();
+ mes(l("To get a quote:"));
+ mes(col(" ~quote anyone", 7));
+ mes(col(" ~quote ##Bplayer name##b", 7));
+ mes(col(" ~quote ##B#number##b", 7));
+ next();
+ mes(l("To remove a quote:"));
+ mes(col(" ~remove quote ##B#number##b", 7));
+ mes(col(" ~remove last quote", 7));
+ next();
+ mes(l("Last seen:"));
+ mes(col(" ~seen ##Bplayer name##b", 7));
+ next();
+ mes(l("To ignore a player:"));
+ mes(col(" ~ignore ##Bplayer name##b", 7));
+ next();
+ mes(l("To unignore a player:"));
+ mes(col(" ~unignore ##Bplayer name##b", 7));
+ next();
+
+ if (is_admin())
+ {
+ mes(l("To trust a player:"));
+ mes(col(" ~trust ##Bplayer name##b", 7));
+ next();
+ mes(l("To de-trust a player:"));
+ mes(col(" ~untrust ##Bplayer name##b", 7));
+ next();
+ }
+ return;
+ }
+
+ do
+ {
+ clear();
+ setnpcdialogtitle(l("Tree Control Panel"));
+ mes(l("Oh noes! You found my secret backdoor!"));
+ next();
+ mes(l("Please select an option:"));
+
+ select(
+ l("List the commands"),
+ rif(is_admin(), l("Empty the quote DB")),
+ l("Dance for me"));
+
+ switch (@menu)
+ {
+ case 1: list_commands(); break;
+ case 2: clear_db(); break;
+ default: speech(l("Too lazy.")); close;
+ }
+
+ } while (true);
+
+ end;
+ }
+
+ // utility functions below
+
+ function check_is_ignored {
+ .@val = htget(.ignore_ht, strcharinfo(PC_NAME), 0);
+
+ if (.@val > gettimetick(2))
+ {
+ ++.ignored_times;
+ end;
+ }
+
+ else if (.@val > 0)
+ {
+ htput(.ignore_ht, strcharinfo(PC_NAME), 0); // remove expired entries
+ }
+
+ return;
+ }
+
+ function special_name {
+ .@name$ = strcharinfo(PC_NAME);
+ .@low$ = strtolower(.@name$);
+
+ if (rand(.sname_rate) == 0)
+ {
+ for (.@i = 0; .@i < .alias; .@i += 2)
+ {
+ if (.@low$ ~= .alias$[.@i])
+ {
+ explode(.@aliases$, .alias$[.@i+1], "`");
+ .@name$ = .@aliases$[rand(getarraysize(.@aliases$))];
+ break;
+ }
+ }
+ }
+
+ return .@name$;
+ }
+
+ function face {
+ if (gettimetick(2) - .last_emote < .emote_rate)
+ {
+ ++.ignored_times;
+ return;
+ }
+
+ .last_emote = gettimetick(2);
+ return emotion(getarg(0, E_SURPRISE));
+ }
+
+ function rp {
+ // used for queries
+ return replacestr(getarg(0,""), "~t", strtolower("(?:" + .name$ + "|" + .hotwords$ + ")"));
+ }
+
+ function format_reply {
+ // used for replies
+ .@str$ = getarg(0, "");
+
+ // search for {{mustaches}}
+ while (.@str$ ~= "{{([^}]+)}}")
+ {
+ .@sub$ = replacestr($@regexmatch$[1], " ", ""); // remove whitespaces
+ .@sub$ = strtolower(.@sub$); // always lowercase the var name
+ .@capitalize = .@titlecase = .@allcaps = false;
+
+ if (charat(.@sub$, 0) == "^")
+ {
+ .@capitalize = true;
+ .@sub$ = substr(.@sub$, 1, getstrlen(.@sub$) - 1); // strip first char
+ }
+
+ else if (charat(.@sub$, 0) == "+")
+ {
+ .@titlecase = true;
+ .@sub$ = substr(.@sub$, 1, getstrlen(.@sub$) - 1); // strip first char
+ }
+
+ else if (charat(.@sub$, 0) == "!")
+ {
+ .@allcaps = true;
+ .@sub$ = substr(.@sub$, 1, getstrlen(.@sub$) - 1); // strip first char
+ }
+
+ explode(.@sub2$, .@sub$, ",");
+ .@sub$ = .@sub2$[rand(getarraysize(.@sub2$))]; // allow to have multiple variables
+
+ .@rep$ = getd(sprintf(".D_%s$[%i]", .@sub$, rand(getd(".D_" + .@sub$)))); // get he value
+
+ if (.@capitalize) .@rep$ = capitalize(.@rep$);
+ else if (.@titlecase) .@rep$ = titlecase(.@rep$);
+ else if (.@allcaps) .@rep$ = strtoupper(.@rep$);
+
+ .@str$ = replacestr(.@str$, $@regexmatch$[0], .@rep$); // remove the mustache, replace by value
+ }
+
+ // search for emotes
+ if (.@str$ ~= "%%([^ ])")
+ {
+ // only handling a few of them
+ switch (ord($@regexmatch$[1]))
+ {
+ case 73: face(any(E_WINK, E_ANGEL)); break;
+ case 83: face(any(E_SAD, E_CRYING)); break;
+ case 85: face(E_SURPRISE); break;
+ case 93: face(any(E_HEARTEYE, E_HEART)); break;
+ case 94: face(E_DISGUST); break;
+ case 99: face(E_DEAD); break;
+ case 105: face(E_CRYING); break;
+ case 106:
+ case 91: face(any(E_SPEECH, E_BLAH)); break;
+ case 107: face(E_INSULTBUBBLE); break;
+ default: .@unhandled = true;
+ }
+
+ if (.@unhandled != true)
+ {
+ if (.@str$ == $@regexmatch$[0]) end; // don't send handled, emote-only messages
+ .@str$ = replacestr(.@str$, " "+ $@regexmatch$[0], ""); // otherwise strip the emote
+ }
+ }
+
+ // built-in variables
+ .@str$ = replacestr(.@str$, "~n", .name$); // npc name
+ .@str$ = replacestr(.@str$, "~p", special_name()); // player name or special name
+ .@str$ = replacestr(.@str$, "~P", strcharinfo(PC_NAME)); // unaltered player name
+
+ return rp(.@str$);
+ }
+
+ function strip_colors {
+ .@str$ = replacestr(getarg(0, ""), "##0", "");
+ .@str$ = replacestr(.@str$, "##1", "");
+ .@str$ = replacestr(.@str$, "##2", "");
+ .@str$ = replacestr(.@str$, "##3", "");
+ .@str$ = replacestr(.@str$, "##4", "");
+ .@str$ = replacestr(.@str$, "##5", "");
+ .@str$ = replacestr(.@str$, "##6", "");
+ .@str$ = replacestr(.@str$, "##7", "");
+ .@str$ = replacestr(.@str$, "##8", "");
+ .@str$ = replacestr(.@str$, "##9", "");
+ return replacestr(.@str$, "##a", "");
+ }
+
+ function strip_formatting {
+ .@str$ = strip_colors(getarg(0, ""));
+ .@str$ = replacestr(.@str$, "##B", "");
+ return replacestr(.@str$, "##b", "");
+ }
+
+ function delayed_reply {
+ ++.answered_times;
+ @tree_reply$ = getarg(0, "");
+ addtimer(.delay_reply, .name$ + "::OnDoReply");
+ return;
+ }
+
+ function reply {
+ .@reply$ = format_reply(getarg(0, ""));
+ getmapxy(.@pc_map$, .@pc_x, .@pc_y, UNITTYPE_PC); // get char location
+
+ if (((.@reply$ == .last_reply$ && gettimetick(2) - .last_reply < .repeat_rate)
+ || gettimetick(2) - .last_reply < .talk_rate
+ || (gettimetick(2) - .blocked < .block_time && is_trusted() == false)
+ || .@pc_map$ != .map$
+ || distance(.x, .y, .@pc_x, .@pc_y) > .distance
+ || .@reply$ == "")
+ && is_dev() == false)
+ {
+ ++.ignored_times;
+ return;
+ }
+
+ .last_reply = gettimetick(2);
+ .last_reply$= .@reply$;
+
+ delayed_reply(.@reply$);
+ return;
+ }
+
+ function seen_me {
+ if (playerattached() > 0)
+ {
+ htput(.seen_ht, strcharinfo(PC_NAME), gettimetick(2));
+ }
+ return;
+ }
+
+ function have_you_seen {
+ .@player$ = getarg(0, "");
+ .@player = getcharid(CHAR_ID_ACCOUNT, .@player$);
+
+ if (.@player > 0)
+ {
+ // nested if, because they don't short-circuit
+ if (checkoption(Option_Invisible, .@player) == false) {
+ delayed_reply(sprintf("Player `%s` is currently online.", .@player$));
+ end;
+ }
+ }
+
+ .@time = htget(.seen_ht, .@player$, 0);
+
+ if (.@time < 1)
+ delayed_reply(sprintf("I haven't seen player `%s` today.", .@player$));
+
+ else
+ delayed_reply(sprintf("Player `%s` was last seen %s.", .@player$, FuzzyTime(.@time)));
+
+ end;
+ }
+
+ function special_drops {
+ .@drop$ = .drops$[rand(.drops)];
+ .@name$ = strcharinfo(PC_NAME);
+ .@low$ = strtolower(.@name$);
+
+ if (rand(.sdrop_rate) == 0)
+ {
+ for (.@i = 0; .@i < .sdrops; .@i += 2)
+ {
+ if (.@low$ ~= .sdrops$[.@i])
+ {
+ explode(.@d$, .sdrops$[.@i+1], "`");
+ .@drop$ = .@d$[rand(getarraysize(.@d$))];
+ break;
+ }
+ }
+ }
+
+ return .@drop$;
+ }
+
+ function roll_dice {
+ .@dices = max(min(getarg(0, 1), 8), 1); // 1..8
+ .@sides = max((getarg(1, 6) < 1 ? 6 : getarg(1, 6)), 1); // 1..MAX_INT
+
+ .@result$ = sprintf("*rolls the dice%s: %d",
+ rif(.@dices > 1, "s"), rand(1, .@sides)); // first dice
+
+ for (.@d = 1; .@d < .@dices; ++.@d)
+ {
+ .@result$ += ", " + rand(1, .@sides);
+ }
+
+ return .@result$ + ".*";
+ }
+
+ function flip_coin {
+ .@coins = getarg(0, 1);
+
+ .@result$ = sprintf("*flips the coin%s: %s",
+ rif(.@coins > 1, "s"), (rand(2) == 1 ? "heads" : "tails")); // first coin
+
+ for (.@c = 1; .@c < .@coins; ++.@c)
+ {
+ .@result$ += ", " + (rand(2) == 1 ? "heads" : "tails");
+ }
+
+ return .@result$ + ".*";
+ }
+
+ function roulette {
+ if (.roulette == 1)
+ {
+ npctalk("*pulls the trigger: *##BBANG##b*.*");
+ delayed_reply("*reloads and spins the chambers.*");
+ .roulette = rand(1, 7); // the Nagant_M1895 has 7 chambers
+
+ // now the fun part
+ nude();
+ percentheal(-100, 0);
+ }
+
+ else
+ {
+ delayed_reply("*pulls the trigger: *click*.*");
+ .roulette = (.roulette == 7 ? 1 : .roulette + 1);
+ }
+
+ end;
+ }
+
+ function monologue_player {
+ return sprintf("Your current monologue is at least %d line%s long.",
+ @monologue, rif(@monologue != 1, "s"));
+ }
+
+ function who_player {
+ return sprintf("You seem to be ##B~P##b [%i:%i].",
+ getcharid(CHAR_ID_ACCOUNT), getcharid(CHAR_ID_CHAR));
+ }
+
+ function make_quote_table {
+ // Do not modify this
+ query_sql("CREATE TABLE IF NOT EXISTS `tree_quotes` ("
+ " `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
+ " `char_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',"
+ " `grabber` INT(11) UNSIGNED NOT NULL DEFAULT '0',"
+ " `timestamp` INT(10) UNSIGNED NOT NULL DEFAULT '0',"
+ " `message` VARCHAR(150) NOT NULL DEFAULT '',"
+ " PRIMARY KEY (`id`),"
+ " KEY `char_id` (`char_id`),"
+ " KEY `grabber` (`grabber`)"
+ ") ENGINE=MyISAM;");
+
+ .last_query = gettimetick(2);
+ return;
+ }
+
+ function grab_quote {
+ .@name$ = getarg(0, "");
+
+ if (gettimetick(2) - .last_query < (is_trusted() ? .qpoll_rate : .qpoll_rate2))
+ {
+ ++.ignored_times;
+ end;
+ }
+
+ if (.@name$ == strcharinfo(PC_NAME))
+ {
+ delayed_reply("##BError: You may not grab yourself.");
+ end;
+ }
+
+ explode(.@tmp$[0], htget(.msg_ht, .@name$, ""), ":"); // get last message, if any
+ htput(.msg_ht, .@name$, ""); // ensure you can't grab twice the same message
+
+ .@char_id = atoi(.@tmp$[0]); // grab the char id part
+
+ if (.@char_id < 1)
+ {
+ delayed_reply(sprintf("##BError: I couldn't find anything to grab from player `%s`.", .@name$));
+ end;
+ }
+
+ .@msg$ = implode(.@tmp$, ":"); // put it back together
+ .@start = getstrlen(.@tmp$[0]) + getstrlen(.@tmp$[1]) + 2; // char:time:msg <= we just want the msg part
+ .@msg$ = escape_sql(strip_formatting(substr(.@msg$, .@start, getstrlen(.@msg$) - 1))); // sanitize
+
+ if (.@msg$ == "")
+ {
+ delayed_reply("##BError: Message is empty or malformed. It cannot be grabbed.");
+ end;
+ }
+
+ else if (.@msg$ ~= "^[!#~@]?(?:grab)?shield(?:ed)?(?:[:.!]? .*)?$")
+ {
+ delayed_reply("##BError: Message is shielded.");
+ end;
+ }
+
+ query_sql(sprintf("INSERT INTO tree_quotes (char_id,grabber,timestamp,message) VALUES (%i,%i,%i,'%s');",
+ .@char_id, getcharid(CHAR_ID_CHAR), gettimetick(2), .@msg$));
+
+ query_sql("SELECT MAX(id) FROM tree_quotes;", .q_last_id); // get the last quote id
+
+ .last_query = gettimetick(2);
+
+ delayed_reply(sprintf("Success: Quote grabbed. (#%i)", .q_last_id));
+ end;
+ }
+
+ function remove_quote {
+ .@tmp = getarg(0, 0);
+
+ if (gettimetick(2) - .last_query < (is_trusted() ? .qpoll_rate : .qpoll_rate2))
+ {
+ ++.ignored_times;
+ end;
+ }
+
+ query_sql(sprintf("SELECT id FROM tree_quotes WHERE id = %i ORDER BY id DESC LIMIT 1;", .@tmp), .@id); // check if it exists
+
+ if (.@id < 1)
+ {
+ delayed_reply(sprintf("##BError: I couldn't find quote #%i in the database.", .@tmp));
+ end;
+ }
+
+ query_sql(sprintf("DELETE FROM tree_quotes WHERE id = %i ORDER BY id DESC LIMIT 1;", .@id));
+
+ .last_query = gettimetick(2);
+
+ delayed_reply(sprintf("Success: Quote removed. (#%i)", .@id));
+ end;
+ }
+
+ function cite_quote {
+ .@id = getarg(0,0);
+
+ if (gettimetick(2) - .last_query < (is_trusted() ? .qpoll_rate : .qpoll_rate2))
+ {
+ ++.ignored_times;
+ end;
+ }
+
+ query_sql(sprintf("SELECT t.id, c.name AS grabee, d.name AS grabber, t.timestamp, t.message "
+ "FROM `tree_quotes` t "
+ "JOIN `char` c ON t.char_id = c.char_id "
+ "JOIN `char` d ON t.grabber = d.char_id "
+ "WHERE t.id=%i ORDER BY t.id DESC LIMIT 1;",
+ .@id),
+ .@nid[0], .@grabee$[0], .@grabber$[0], .@time[0], .@msg$[0]);
+
+ .last_query = gettimetick(2);
+
+ if (.@nid[0] < 1)
+ {
+ delayed_reply(sprintf("##BError: I couldn't find quote #%i in the database.", .@id));
+ end;
+ }
+
+ delayed_reply(sprintf("<%s> ##B%s##b ##a— grabbed by %s %s.",
+ .@grabee$[0], .@msg$[0], .@grabber$[0], FuzzyTime(.@time[0],0,1)));
+ end;
+ }
+
+ function random_quote {
+ .@name$ = escape_sql(getarg(0, ""));
+
+ if (gettimetick(2) - .last_query < (is_trusted() ? .qpoll_rate : .qpoll_rate2))
+ {
+ ++.ignored_times;
+ end;
+ }
+
+ query_sql("SELECT t.id, c.name AS grabee, d.name AS grabber, t.timestamp, t.message "
+ "FROM `char` c "
+ "JOIN `tree_quotes` t ON t.char_id = c.char_id "
+ "JOIN `char` d ON d.char_id = t.grabber " +
+ rif(.@name$ != "", sprintf("WHERE c.name='%s' ", .@name$)) +
+ "ORDER BY RAND() LIMIT 1;",
+ .@nid[0], .@grabee$[0], .@grabber$[0], .@time[0], .@msg$[0]);
+
+ .last_query = gettimetick(2);
+
+ if (.@nid[0] < 1)
+ {
+ if (.@name$ != "")
+ delayed_reply(sprintf("##BError: I couldn't find any quote from `%s` in the database.", getarg(0, "")));
+ else
+ delayed_reply("##BError: The quote database is empty.");
+ end;
+ }
+
+ delayed_reply(sprintf("<%s> ##B%s##b ##a— grabbed by %s %s. (#%i)",
+ .@grabee$[0], .@msg$[0], .@grabber$[0], FuzzyTime(.@time[0],0,1), .@nid[0]));
+ end;
+ }
+
+ function trigger_hotword {
+ .@o$ = getarg(0, ""); // original lowercase
+ .@m$ = replacestr(.@o$, "*", ""); // original lowercase clean
+
+
+ if (.@m$ ~= "(?:^| )tell(?: (?:me|him|her|us|them))? a(?:n ?other| lame| bad| boring)? joke")
+ reply(.jokes$[rand(.jokes)]);
+
+ else if (.@m$ ~= "(?:^| )heal me(?:$|[^a-z])")
+ reply(.healing$[rand(.healing)]);
+ // XXX: maybe actually heal the player once in a while
+
+ else if (.@m$ ~= "(?:^| )(?:what|who) are you")
+ reply(.whoami$[rand(.whoami)]);
+
+ else if (.@m$ ~= rp("(?:^| )(?:hi+|hello|heya?|hiya|good (?:morning|afternoon))[^a-z]* .*~t|~t.* (?:hi+|hello|heya?|hiya)"))
+ {
+ .blocked = 0;
+ reply(.greetings$[rand(.greetings)]);
+ }
+
+ else if (.@o$ ~= rp("(?:^[*]| )(?:kicks?|shakes?) .*~t"))
+ reply(special_drops());
+
+ else if (.@o$ ~= rp("(?:^[*]| )(?:cuts?|nukes?|kills?|chops? down|saws?|hews?|murders?) .*~t"))
+ reply(.kill$[rand(.kill)]);
+
+ else if (.@o$ ~= rp("(?:^[*]| )pokes? .*~t"))
+ reply(.poke$[rand(.poke)]);
+
+ else if (.@o$ ~= rp("(?:^[*]| )(?:waters?|pees?|licks?) .*~t"))
+ reply(.disgusting$[rand(.disgusting)]);
+
+ else if (compare(.@m$, " answer ") && .@m$ ~= "(?:life|universe|everything)(?:$|[^a-z])")
+ reply(.answer$[rand(.answer)]);
+
+ else if (.@o$ ~= rp("(?:^[*]| )(?:burns?|incinerates?|ignites?) .*~t"))
+ reply(.burning$[rand(.burning)]);
+ // XXX: maybe here send a fire particle effect
+
+ else if (.@m$ ~= rp("(?:^| )die ~t"))
+ reply(.die$[rand(.die)]);
+
+ else if (.@o$ ~= rp("(?:^[*]| )bites? .*~t|(?:^[*]| )drops? .* on ~t"))
+ reply(.silly$[rand(.silly)]);
+
+ else if (.@m$ ~= rp("(?:^| )(?:loves?|hugs?|kiss(es)?) .*~t|~t.* love(?:$|[^a-z])"))
+ reply(.love$[rand(.love)]);
+
+ else if (.@m$ ~= rp("(?:^| )dance .*~t|~t.* dance(?:$|[^a-z])"))
+ reply(.dance$[rand(.dance)]);
+
+ else if (.@m$ ~= rp("(?:^| )hates? .*~t"))
+ reply(.hate$[rand(.hate)]);
+
+ else if (.@o$ ~= rp("(?:^[*]| )(?:eats?|shoots?|plucks?|tortures?|slaps?|slaps?|poisons?|breaks?|stabs?|throws?|punch(?:es)?) .*~t"))
+ reply(.pain$[rand(.pain)]);
+
+ else if (.@o$ ~= rp("(?:^[*]| )(?:climbs?|rides?|mounts?) .*~t"))
+ reply(.climb$[rand(.climb)]);
+
+ else if (.@m$ ~= "(?:^| )(?:see y(?:a|ou)|good night|(?:bye)?bye+)(?:$|[^a-z])")
+ reply(.bye$[rand(.bye)]);
+
+ else if (.@m$ ~= rp("(?:^| )bad ~t"))
+ reply(.bad$[rand(.bad)]);
+
+ else if (.@m$ ~= "(?:^| )(?:how old are you|uptime)(?:$|[^a-z])")
+ reply("%%B Server uptime: " + FuzzyTime(.uptime, 1) + ".");
+
+ else if (.@m$ ~= "(?:^| )how chatty are you(?:$|[^a-z])")
+ reply("%%B Answered " + .answered_times + " times, ignored " + .ignored_times + " times.");
+
+ else if (.@m$ ~= "(?:^| )what.* version(?:$|[^a-z])")
+ reply("%%B ~n, version " + .version + "."); // XXX: maybe return Hercules version and serverdata commit instead
+
+ else if (.@m$ ~= "(?:^| )(?:(?:8|eight)[ -]?ball|(?:should|would|will|do|does) (?:i|you|he|she|it|we|they))(?:$|[^a-z])")
+ reply(.eightball$[rand(.eightball)]);
+
+ else if (.@m$ ~= "(?:^| )roll(?: a| the)? dice(?:$|[^a-z])")
+ reply(roll_dice(1, 6));
+
+ else if (.@m$ ~= "(?:^| )roll(?: a)? ([1-8])d((?:[1-9][0-9]{0,10})?)(?:$|[^0-9a-z])")
+ reply(roll_dice(atoi($@regexmatch$[1]), atoi($@regexmatch$[2])));
+
+ else if (.@m$ ~= "(?:^| )roll ([1-8]) dices?(?:$|[^a-z])")
+ reply(roll_dice(atoi($@regexmatch$[1]), 6));
+
+ else if (.@m$ ~= "(?:^| )(?:flip|toss)(?: a| the)? coin(?:$|[^a-z])")
+ reply(flip_coin(1));
+
+ else if (.@m$ ~= "(?:^| )(?:flip|toss) ([1-8]) coins?(?:$|[^a-z])")
+ reply(flip_coin(atoi($@regexmatch$[1])));
+
+ else if (.@m$ ~= "(?:^| )(?:press|pull)(?: the)? trigger(?:$|[^a-z])")
+ roulette();
+
+ else if (.@m$ ~= "(?:^| )(?:how long|what) is(?: my)? monologue(?:$|[^a-z])")
+ reply(monologue_player());
+
+ else if (.@m$ ~= "(?:^| )who am i(?:$|[^a-z])")
+ reply(who_player());
+
+ else if (.@m$ ~= "(?:^| )shut up(?:$|[^a-z])")
+ {
+ reply(.shut_up$[rand(.shut_up)]);
+ .blocked = gettimetick(2);
+ }
+
+ else if (rand(.dunno_rate) == 0)
+ reply(.no_idea$[rand(.no_idea)]);
+
+ else
+ ++.ignored_times;
+
+ end;
+ }
+
+ function trigger_hiall {
+ if (rand(.hiall_rate) == 0)
+ reply(.greetings$[rand(.greetings)]);
+
+ else
+ ++.ignored_times;
+
+ end;
+ }
+
+OnClick:
+ tree_panel();
+ bye;
+
+
+OnTalkNearby:
+ .@no_nick$ = strip(strip_formatting(substr($@p0$, getstrlen(strcharinfo(PC_NAME)) + 3, getstrlen($@p0$) - 1))); // not very obvious stuff
+ .@no_nick_lower$ = strtolower(.@no_nick$); // FIXME: hercules doesn't have a way to do case insensitive regex yet
+ .@no_nick_clean$ = replacestr(.@no_nick_lower$, "*", "");
+
+ htput(.msg_ht, strcharinfo(PC_NAME), getcharid(CHAR_ID_CHAR) + ":" + gettimetick(2) + ":" + .@no_nick$); // log last message, for quotegrabs
+ .lastsender = getcharid(CHAR_ID_CHAR); // for monologue
+
+ .last_activity = gettimetick(2); // for the auto-janitor
+
+ if ((is_trusted() || #Tree_Trusted) && charat(.@no_nick$, 0) == .symbol$)
+ {
+ if (.@no_nick$ ~= "^.grab \"?([^#:@\"]{4,23})\"?$")
+ reply(grab_quote($@regexmatch$[1]));
+
+ else if (.@no_nick$ ~= "^.(?:ungrab|remove|delete)(?: quote)? #([0-9]+)$")
+ reply(remove_quote(atoi($@regexmatch$[1])));
+
+ else if (.@no_nick$ ~= "^.(?:ungrab|remove|delete)(?: last(?: quote)?)?$")
+ reply(remove_quote(.q_last_id));
+
+ else if (.@no_nick$ ~= "^.(?:quote|cite) #([0-9]+)$")
+ reply(cite_quote(atoi($@regexmatch$[1])));
+
+ else if (.@no_nick$ ~= "^.(?:(?:random )?quote|cite)(?: anyone| someone| random)?$")
+ reply(random_quote());
+
+ else if (.@no_nick$ ~= "^.(?:quote|cite) \"?([^#:@\"]{4,23})\"?$")
+ reply(random_quote($@regexmatch$[1]));
+
+ else if (.@no_nick$ ~= "^.seen \"?([^#:@\"]{4,23})\"?$")
+ reply(have_you_seen($@regexmatch$[1]));
+
+ // to allow trusted testers to reboot without knowing the exit code
+ else if (debug && .@no_nick$ ~= "^.re(?:boot|load|start)(?:(?: the)? server)?$")
+ {
+ announce("The server is rebooting. This may take a couple minutes.", bc_all);
+ sleep2(1000);
+ atcommand("@serverexit 104");
+ }
+
+ // exit, pull all, clean, build, reboot
+ else if (debug && .@no_nick$ ~= "^.re-?build(?:(?: the)? server)?$")
+ {
+ announce("The server is rebuilding. This will take several minutes.", bc_all);
+ sleep2(1000);
+ atcommand("@serverexit 108");
+ }
+
+ else if (.@no_nick$ ~= "^.(?:add )?ignored? \"?([^#:@\"]{4,23})\"?$")
+ {
+ .@chr = getcharid(CHAR_ID_ACCOUNT, $@regexmatch$[1]);
+ if (.@chr < 1)
+ {
+ reply("##BError: Player not found or not online.");
+ end;
+ }
+ htput(.ignore_ht, strcharinfo(PC_NAME, .@chr), gettimetick(2) + 3600);
+ reply(sprintf("Success: Player `%s` is now ignored for 1 hour.",
+ strcharinfo(PC_NAME, .@chr)));
+ }
+
+ else if (.@no_nick$ ~= "^.(?:un|de-?|remove )ignored? \"?([^#:@\"]{4,23})\"?$")
+ {
+ .@chr = getcharid(CHAR_ID_ACCOUNT, $@regexmatch$[1]);
+ if (.@chr < 1)
+ {
+ reply("##BError: Player not found or not online.");
+ end;
+ }
+ htput(.ignore_ht, strcharinfo(PC_NAME, .@chr), 0);
+ reply(sprintf("Success: Player `%s` is no longer ignored.",
+ strcharinfo(PC_NAME, .@chr)));
+ }
+
+ else if (is_admin() && .@no_nick$ ~= "^.(?:add )?trust(?:ed)? \"?([^#:@\"]{4,23})\"?$")
+ {
+ .@chr = getcharid(CHAR_ID_ACCOUNT, $@regexmatch$[1]);
+ if (.@chr < 1)
+ {
+ reply("##BError: Player not found or not online.");
+ end;
+ }
+ set(getvariableofpc(#Tree_Trusted, .@chr), true);
+ reply(sprintf("Success: Player `%s` can now use restricted commands.",
+ strcharinfo(PC_NAME, .@chr)));
+ }
+
+ else if (is_admin() && .@no_nick$ ~= "^.(?:un|de-?|remove )trust(?:ed)? \"?([^#:@\"]{4,23})\"?$")
+ {
+ .@chr = getcharid(CHAR_ID_ACCOUNT, $@regexmatch$[1]);
+ if (.@chr < 1)
+ {
+ reply("##BError: Player not found or not online.");
+ end;
+ }
+ set(getvariableofpc(#Tree_Trusted, .@chr), false);
+ reply(sprintf("Success: Player `%s` can no longer use restricted commands.",
+ strcharinfo(PC_NAME, .@chr)));
+ }
+
+ else
+ reply("##BError: Command not found or invalid syntax.");
+ }
+
+ else if (.@no_nick_lower$ ~= rp("^(~t[^a-z ]* .*|(?:.* (?:~t[^a-z ]* .*|~t[^ a-z]*)))$"))
+ {
+ check_is_ignored();
+ trigger_hotword($@regexmatch$[1]);
+ }
+
+ else if (.@no_nick_clean$ ~= "^(hi(ya)?|hello|heya?) (all|friends|every(one|body))")
+ {
+ check_is_ignored();
+ trigger_hiall();
+ }
+
+ else
+ {
+ if (.lastsender == getcharid(CHAR_ID_CHAR))
+ @monologue++;
+
+ else
+ @monologue = 1;
+ }
+
+ // TODO: eliza mode, whisper eliza mode
+ end;
+
+OnTouch:
+ if (rand(.touch_rate) == 0) {
+ face();
+ }
+ end;
+
+OnDoReply:
+ if (@tree_reply$ != "") {
+ npctalk(@tree_reply$);
+ @tree_reply$ = "";
+ }
+ end;
+
+OnPCLogoutEvent:
+ seen_me();
+ end;
+
+OnTimer3600000:
+ // scheduled janitor
+ .@now = gettimetick(2);
+ initnpctimer(); // schedule next
+
+ if (.last_activity > (.@now - 3600)) {
+ end; // last activity is too recent
+ }
+
+ // cleanup routine below
+ .lastsender = 0;
+ .last_activity = 0;
+ .last_reply = 0;
+ .last_emote = 0;
+ .last_query = 0;
+ .blocked = 0;
+ .enable_janitor = 0;
+
+ htclear(.msg_ht); // empty the message table (quotegrabs)
+ htclear(.ignore_ht); // empty the ignore table
+
+ .@it = htiterator(.seen_ht); // allocate new iterator
+ for (.@key$ = htinextkey(.@it); hticheck(.@it); .@key$ = htinextkey(.@it)) {
+ if (.@key$ == "") {
+ continue;
+ }
+
+ if (htget(.seen_ht, .@key$, 0) < (.@now - 86400)) {
+ htput(.seen_ht, .@key$, 0); // remove from hash table if older than 24h
+ }
+ }
+ htidelete(.@it); // free the iterator
+
+ face(); // do an emote (because why not)
+ end;
+
+
+OnDay0320:
+ .dir = DOWNLEFT;
+ end;
+
+
+OnDay0621:
+ .dir = LEFT;
+ end;
+
+
+OnDay0922:
+ .dir = UPLEFT;
+ end;
+
+
+OnDay1221:
+ .dir = DOWN;
+ end;
+
+
+OnInit:
+ // config below
+ .hotwords$ = "tree"; // what hot words the npc should listen to, besides its own name (regex)
+ .distance = 14; // the npc will only listen to player within X tiles
+ .sex = G_OTHER; // gender of the npc
+ .dir = season_direction(); // sprite direction according to the season
+ .talk_rate = 1; // min number of seconds to wait between replies
+ .repeat_rate = 1; // min number of seconds to wait before sending the same message twice in a row
+ .block_time = 600; // how long to stay quiet after someone says shut up, in seconds
+ .emote_rate = 3; // min number of seconds to wait between emotes
+ .sdrop_rate = 8; // 1 in X chances to get a special drop
+ .sname_rate = 8; // 1 in X chances to get a special name
+ .dunno_rate = 2; // 1 in X chances to get a reply when the command is not found
+ .hiall_rate = 2; // 1 in X chances to reply to a "hi everyone"
+ .touch_rate = 4; // 1 in X chances to trigger the OnTouch action
+ .qpoll_rate = 1; // min number of seconds to wait before calling the sql db again for GMs
+ .qpoll_rate2 = 5; // min number of seconds to wait before calling the sql db again for non-GMs (currently unused)
+ .delay_reply = 250; // number of ms to wait to reply
+ .enable_janitor = true; // automatically free memory when idle
+ .symbol$ = "~"; // symbol for GM-only commands
+
+ // register some arrays
+ callfunc("TREE_dictionaries");
+
+ // do random stuff
+ make_quote_table();
+ face();
+
+ // boring stuff below
+ .version = 21; // increase this when you make a change
+ .uptime = gettimetick(2);
+ .alwaysVisible = true; // the NPC doesn't de-spawn when moving away
+ .pid = 1; // regex pattern id
+ .msg_ht = htnew(); // hashtable id for message history
+ .seen_ht = htnew(); // hashtable id for seen log
+ .ignore_ht = htnew(); // hashtable id for ignored players
+ .roulette = rand(1, 7); // spin the chambers
+ defpattern(.pid, "^(.*)$", "OnTalkNearby");
+ activatepset(.pid);
+ if (.enable_janitor) {
+ initnpctimer();
+ }
+}
+
+// Duplicates below
+//000-1,42,63,0 duplicate(Confused Tree) Confused Palm Tree NPC_NO_SPRITE,14,14
diff --git a/npc/008-1/doors.txt b/npc/008-1/doors.txt
new file mode 100644
index 000000000..de8ed1d8e
--- /dev/null
+++ b/npc/008-1/doors.txt
@@ -0,0 +1,6 @@
+008-1,104,27,0 script CottageDoor NPC_WARP,0,0,{
+ end;
+
+OnTouch:
+ dispbottom(l("Locked."));
+}
diff --git a/npc/008-1/mapflags.txt b/npc/008-1/mapflags.txt
new file mode 100644
index 000000000..f2680964c
--- /dev/null
+++ b/npc/008-1/mapflags.txt
@@ -0,0 +1 @@
+008-1 mapflag town
diff --git a/npc/008-1/wateranimation.txt b/npc/008-1/wateranimation.txt
new file mode 100644
index 000000000..8b66f637e
--- /dev/null
+++ b/npc/008-1/wateranimation.txt
@@ -0,0 +1,9 @@
+// Evol scripts.
+// Author:
+// gumi
+// Reid
+// Description:
+// Water animations, splash, fishes, etc...
+
+008-1,139,32,0 duplicate(#water_animation0) #water_animation16 NPC_WATER_SPLASH
+008-1,140,40,0 duplicate(#water_animation0) #water_animation17 NPC_WATER_SPLASH
diff --git a/npc/008-2-0/_import.txt b/npc/008-2-0/_import.txt
new file mode 100644
index 000000000..f2ecc3b88
--- /dev/null
+++ b/npc/008-2-0/_import.txt
@@ -0,0 +1,5 @@
+// Map 008-2-0: Chez Celestia
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-0/_savepoints.txt",
+"npc/008-2-0/_warps.txt",
+"npc/008-2-0/mapflags.txt",
diff --git a/npc/008-2-0/_savepoints.txt b/npc/008-2-0/_savepoints.txt
new file mode 100644
index 000000000..d9055b64d
--- /dev/null
+++ b/npc/008-2-0/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-0: Chez Celestia saves
+008-2-0,37,27,0 script #save_008-2-0_37_27 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/008-2-0/_warps.txt b/npc/008-2-0/_warps.txt
new file mode 100644
index 000000000..72a8ab127
--- /dev/null
+++ b/npc/008-2-0/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-0: Chez Celestia warps
+008-2-0,26,22,0 warp #008-2-0_26_22 0,0,008-1,105,75
+008-2-0,22,34,0 warp #008-2-0_22_34 0,0,008-1,101,79
diff --git a/npc/008-2-0/mapflags.txt b/npc/008-2-0/mapflags.txt
new file mode 100644
index 000000000..93df75f47
--- /dev/null
+++ b/npc/008-2-0/mapflags.txt
@@ -0,0 +1 @@
+008-2-0 mapflag town
diff --git a/npc/008-2-1/_import.txt b/npc/008-2-1/_import.txt
new file mode 100644
index 000000000..1e5137a76
--- /dev/null
+++ b/npc/008-2-1/_import.txt
@@ -0,0 +1,5 @@
+// Map 008-2-1: Merchant Guild
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-1/_savepoints.txt",
+"npc/008-2-1/_warps.txt",
+"npc/008-2-1/mapflags.txt",
diff --git a/npc/008-2-1/_savepoints.txt b/npc/008-2-1/_savepoints.txt
new file mode 100644
index 000000000..66730940b
--- /dev/null
+++ b/npc/008-2-1/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-1: Merchant Guild saves
+008-2-1,42,27,0 script #save_008-2-1_42_27 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/008-2-1/_warps.txt b/npc/008-2-1/_warps.txt
new file mode 100644
index 000000000..e47cbf73f
--- /dev/null
+++ b/npc/008-2-1/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-1: Merchant Guild warps
+008-2-1,37,27,0 warp #008-2-1_37_27 0,0,008-1,89,66
+008-2-1,33,43,0 warp #008-2-1_33_43 0,0,008-1,88,72
diff --git a/npc/008-2-1/mapflags.txt b/npc/008-2-1/mapflags.txt
new file mode 100644
index 000000000..788994890
--- /dev/null
+++ b/npc/008-2-1/mapflags.txt
@@ -0,0 +1 @@
+008-2-1 mapflag town
diff --git a/npc/008-2-10/_import.txt b/npc/008-2-10/_import.txt
new file mode 100644
index 000000000..994726eb8
--- /dev/null
+++ b/npc/008-2-10/_import.txt
@@ -0,0 +1,4 @@
+// Map 008-2-10: Hurnscald City Hall
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-10/_warps.txt",
+"npc/008-2-10/mapflags.txt",
diff --git a/npc/008-2-10/_warps.txt b/npc/008-2-10/_warps.txt
new file mode 100644
index 000000000..25390f950
--- /dev/null
+++ b/npc/008-2-10/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-10: Hurnscald City Hall warps
+008-2-10,37,34,0 warp #008-2-10_37_34 0,0,008-1,102,70
+008-2-10,37,25,0 warp #008-2-10_37_25 1,0,008-2-11,36,27
diff --git a/npc/008-2-10/mapflags.txt b/npc/008-2-10/mapflags.txt
new file mode 100644
index 000000000..7635bed51
--- /dev/null
+++ b/npc/008-2-10/mapflags.txt
@@ -0,0 +1 @@
+008-2-10 mapflag town
diff --git a/npc/008-2-11/_import.txt b/npc/008-2-11/_import.txt
new file mode 100644
index 000000000..84ad9ceb3
--- /dev/null
+++ b/npc/008-2-11/_import.txt
@@ -0,0 +1,5 @@
+// Map 008-2-11: Hurnscald City Hall
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-11/_savepoints.txt",
+"npc/008-2-11/_warps.txt",
+"npc/008-2-11/mapflags.txt",
diff --git a/npc/008-2-11/_savepoints.txt b/npc/008-2-11/_savepoints.txt
new file mode 100644
index 000000000..c3cf65fc7
--- /dev/null
+++ b/npc/008-2-11/_savepoints.txt
@@ -0,0 +1,20 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-11: Hurnscald City Hall saves
+008-2-11,25,27,0 script #save_008-2-11_25_27 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+008-2-11,45,27,0 script #save_008-2-11_45_27 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/008-2-11/_warps.txt b/npc/008-2-11/_warps.txt
new file mode 100644
index 000000000..6c8c4732e
--- /dev/null
+++ b/npc/008-2-11/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-11: Hurnscald City Hall warps
+008-2-11,37,28,0 warp #008-2-11_37_28 1,0,008-2-10,36,26
diff --git a/npc/008-2-11/mapflags.txt b/npc/008-2-11/mapflags.txt
new file mode 100644
index 000000000..3e084fc01
--- /dev/null
+++ b/npc/008-2-11/mapflags.txt
@@ -0,0 +1 @@
+008-2-11 mapflag town
diff --git a/npc/008-2-12/_import.txt b/npc/008-2-12/_import.txt
new file mode 100644
index 000000000..88a854e49
--- /dev/null
+++ b/npc/008-2-12/_import.txt
@@ -0,0 +1,4 @@
+// Map 008-2-12: Hurnscald Clinic
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-12/_warps.txt",
+"npc/008-2-12/mapflags.txt",
diff --git a/npc/008-2-12/_warps.txt b/npc/008-2-12/_warps.txt
new file mode 100644
index 000000000..e44e71548
--- /dev/null
+++ b/npc/008-2-12/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-12: Hurnscald Clinic warps
+008-2-12,30,32,0 warp #008-2-12_30_32 0,0,008-1,110,57
+008-2-12,36,27,0 warp #008-2-12_36_27 1,0,008-2-13,35,31
diff --git a/npc/008-2-12/mapflags.txt b/npc/008-2-12/mapflags.txt
new file mode 100644
index 000000000..b52526a74
--- /dev/null
+++ b/npc/008-2-12/mapflags.txt
@@ -0,0 +1 @@
+008-2-12 mapflag town
diff --git a/npc/008-2-13/_import.txt b/npc/008-2-13/_import.txt
new file mode 100644
index 000000000..a4b0330ec
--- /dev/null
+++ b/npc/008-2-13/_import.txt
@@ -0,0 +1,5 @@
+// Map 008-2-13: Hurnscald Clinic
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-13/_savepoints.txt",
+"npc/008-2-13/_warps.txt",
+"npc/008-2-13/mapflags.txt",
diff --git a/npc/008-2-13/_savepoints.txt b/npc/008-2-13/_savepoints.txt
new file mode 100644
index 000000000..5c8fc22d8
--- /dev/null
+++ b/npc/008-2-13/_savepoints.txt
@@ -0,0 +1,38 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-13: Hurnscald Clinic saves
+008-2-13,29,27,0 script #save_008-2-13_29_27 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+008-2-13,32,27,0 script #save_008-2-13_32_27 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+008-2-13,29,31,0 script #save_008-2-13_29_31 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
+008-2-13,32,31,0 script #save_008-2-13_32_31 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/008-2-13/_warps.txt b/npc/008-2-13/_warps.txt
new file mode 100644
index 000000000..f96812844
--- /dev/null
+++ b/npc/008-2-13/_warps.txt
@@ -0,0 +1,4 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-13: Hurnscald Clinic warps
+008-2-13,36,32,0 warp #008-2-13_36_32 1,0,008-2-12,35,28
+008-2-13,25,26,0 warp #008-2-13_25_26 1,0,008-2-14,24,30
diff --git a/npc/008-2-13/mapflags.txt b/npc/008-2-13/mapflags.txt
new file mode 100644
index 000000000..be0ed6a2c
--- /dev/null
+++ b/npc/008-2-13/mapflags.txt
@@ -0,0 +1 @@
+008-2-13 mapflag town
diff --git a/npc/008-2-14/_import.txt b/npc/008-2-14/_import.txt
new file mode 100644
index 000000000..29a984e8e
--- /dev/null
+++ b/npc/008-2-14/_import.txt
@@ -0,0 +1,5 @@
+// Map 008-2-14: Hurnscald Clinic
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-14/_savepoints.txt",
+"npc/008-2-14/_warps.txt",
+"npc/008-2-14/mapflags.txt",
diff --git a/npc/008-2-14/_savepoints.txt b/npc/008-2-14/_savepoints.txt
new file mode 100644
index 000000000..cbb6fd12b
--- /dev/null
+++ b/npc/008-2-14/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-14: Hurnscald Clinic saves
+008-2-14,31,27,0 script #save_008-2-14_31_27 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/008-2-14/_warps.txt b/npc/008-2-14/_warps.txt
new file mode 100644
index 000000000..241626bb8
--- /dev/null
+++ b/npc/008-2-14/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-14: Hurnscald Clinic warps
+008-2-14,25,31,0 warp #008-2-14_25_31 1,0,008-2-13,24,27
diff --git a/npc/008-2-14/mapflags.txt b/npc/008-2-14/mapflags.txt
new file mode 100644
index 000000000..4f5bd95cf
--- /dev/null
+++ b/npc/008-2-14/mapflags.txt
@@ -0,0 +1 @@
+008-2-14 mapflag town
diff --git a/npc/008-2-2/_import.txt b/npc/008-2-2/_import.txt
new file mode 100644
index 000000000..5a896da02
--- /dev/null
+++ b/npc/008-2-2/_import.txt
@@ -0,0 +1,4 @@
+// Map 008-2-2: The Rusty Pick
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-2/_warps.txt",
+"npc/008-2-2/mapflags.txt",
diff --git a/npc/008-2-2/_warps.txt b/npc/008-2-2/_warps.txt
new file mode 100644
index 000000000..8410ef2bd
--- /dev/null
+++ b/npc/008-2-2/_warps.txt
@@ -0,0 +1,6 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-2: The Rusty Pick warps
+008-2-2,28,34,0 warp #008-2-2_28_34 0,0,008-1,65,56
+008-2-2,52,25,0 warp #008-2-2_52_25 1,0,008-2-3,66,28
+008-2-2,24,29,0 warp #008-2-2_24_29 0,0,008-2-4,43,28
+008-2-2,52,32,0 warp #008-2-2_52_32 0,0,008-2-5,24,25
diff --git a/npc/008-2-2/mapflags.txt b/npc/008-2-2/mapflags.txt
new file mode 100644
index 000000000..8f90e197a
--- /dev/null
+++ b/npc/008-2-2/mapflags.txt
@@ -0,0 +1 @@
+008-2-2 mapflag town
diff --git a/npc/008-2-3/_import.txt b/npc/008-2-3/_import.txt
new file mode 100644
index 000000000..ed172cc7f
--- /dev/null
+++ b/npc/008-2-3/_import.txt
@@ -0,0 +1,4 @@
+// Map 008-2-3: The Rusty Pick
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-3/_warps.txt",
+"npc/008-2-3/mapflags.txt",
diff --git a/npc/008-2-3/_warps.txt b/npc/008-2-3/_warps.txt
new file mode 100644
index 000000000..957ed686d
--- /dev/null
+++ b/npc/008-2-3/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-3: The Rusty Pick warps
+008-2-3,67,29,0 warp #008-2-3_67_29 1,0,008-2-2,51,26
diff --git a/npc/008-2-3/mapflags.txt b/npc/008-2-3/mapflags.txt
new file mode 100644
index 000000000..947a2df34
--- /dev/null
+++ b/npc/008-2-3/mapflags.txt
@@ -0,0 +1 @@
+008-2-3 mapflag town
diff --git a/npc/008-2-4/_import.txt b/npc/008-2-4/_import.txt
new file mode 100644
index 000000000..8ab4d7421
--- /dev/null
+++ b/npc/008-2-4/_import.txt
@@ -0,0 +1,5 @@
+// Map 008-2-4: The Rusty Pick
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-4/_savepoints.txt",
+"npc/008-2-4/_warps.txt",
+"npc/008-2-4/mapflags.txt",
diff --git a/npc/008-2-4/_savepoints.txt b/npc/008-2-4/_savepoints.txt
new file mode 100644
index 000000000..103787d19
--- /dev/null
+++ b/npc/008-2-4/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-4: The Rusty Pick saves
+008-2-4,25,27,0 script #save_008-2-4_25_27 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/008-2-4/_warps.txt b/npc/008-2-4/_warps.txt
new file mode 100644
index 000000000..2d8336f7b
--- /dev/null
+++ b/npc/008-2-4/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-4: The Rusty Pick warps
+008-2-4,44,28,0 warp #008-2-4_44_28 0,0,008-2-2,25,29
diff --git a/npc/008-2-4/mapflags.txt b/npc/008-2-4/mapflags.txt
new file mode 100644
index 000000000..cd86a1e45
--- /dev/null
+++ b/npc/008-2-4/mapflags.txt
@@ -0,0 +1 @@
+008-2-4 mapflag town
diff --git a/npc/008-2-5/_import.txt b/npc/008-2-5/_import.txt
new file mode 100644
index 000000000..74e70e1c5
--- /dev/null
+++ b/npc/008-2-5/_import.txt
@@ -0,0 +1,4 @@
+// Map 008-2-5: The Rusty Pick
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-5/_warps.txt",
+"npc/008-2-5/mapflags.txt",
diff --git a/npc/008-2-5/_warps.txt b/npc/008-2-5/_warps.txt
new file mode 100644
index 000000000..21b7f527b
--- /dev/null
+++ b/npc/008-2-5/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-5: The Rusty Pick warps
+008-2-5,24,24,0 warp #008-2-5_24_24 0,0,008-2-2,52,31
diff --git a/npc/008-2-5/mapflags.txt b/npc/008-2-5/mapflags.txt
new file mode 100644
index 000000000..435dd353f
--- /dev/null
+++ b/npc/008-2-5/mapflags.txt
@@ -0,0 +1 @@
+008-2-5 mapflag town
diff --git a/npc/008-2-6/_import.txt b/npc/008-2-6/_import.txt
new file mode 100644
index 000000000..4630df43d
--- /dev/null
+++ b/npc/008-2-6/_import.txt
@@ -0,0 +1,4 @@
+// Map 008-2-6: Two Guys One Bed
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-6/_warps.txt",
+"npc/008-2-6/mapflags.txt",
diff --git a/npc/008-2-6/_warps.txt b/npc/008-2-6/_warps.txt
new file mode 100644
index 000000000..98944d508
--- /dev/null
+++ b/npc/008-2-6/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-6: Two Guys One Bed warps
+008-2-6,27,33,0 warp #008-2-6_27_33 0,0,008-1,89,59
diff --git a/npc/008-2-6/mapflags.txt b/npc/008-2-6/mapflags.txt
new file mode 100644
index 000000000..c07673a41
--- /dev/null
+++ b/npc/008-2-6/mapflags.txt
@@ -0,0 +1 @@
+008-2-6 mapflag town
diff --git a/npc/008-2-7/_import.txt b/npc/008-2-7/_import.txt
new file mode 100644
index 000000000..263e5dcfc
--- /dev/null
+++ b/npc/008-2-7/_import.txt
@@ -0,0 +1,5 @@
+// Map 008-2-7: Hurnscald Apothecary
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-7/_savepoints.txt",
+"npc/008-2-7/_warps.txt",
+"npc/008-2-7/mapflags.txt",
diff --git a/npc/008-2-7/_savepoints.txt b/npc/008-2-7/_savepoints.txt
new file mode 100644
index 000000000..f3faa80f4
--- /dev/null
+++ b/npc/008-2-7/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-7: Hurnscald Apothecary saves
+008-2-7,25,27,0 script #save_008-2-7_25_27 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/008-2-7/_warps.txt b/npc/008-2-7/_warps.txt
new file mode 100644
index 000000000..3eb8538a6
--- /dev/null
+++ b/npc/008-2-7/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-7: Hurnscald Apothecary warps
+008-2-7,36,29,0 warp #008-2-7_36_29 0,0,008-1,101,56
diff --git a/npc/008-2-7/mapflags.txt b/npc/008-2-7/mapflags.txt
new file mode 100644
index 000000000..caeb89e98
--- /dev/null
+++ b/npc/008-2-7/mapflags.txt
@@ -0,0 +1 @@
+008-2-7 mapflag town
diff --git a/npc/008-2-8/_import.txt b/npc/008-2-8/_import.txt
new file mode 100644
index 000000000..d33465915
--- /dev/null
+++ b/npc/008-2-8/_import.txt
@@ -0,0 +1,4 @@
+// Map 008-2-8: Hurnscald Forge
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-8/_warps.txt",
+"npc/008-2-8/mapflags.txt",
diff --git a/npc/008-2-8/_warps.txt b/npc/008-2-8/_warps.txt
new file mode 100644
index 000000000..7e791e85c
--- /dev/null
+++ b/npc/008-2-8/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-8: Hurnscald Forge warps
+008-2-8,37,39,0 warp #008-2-8_37_39 1,0,008-1,120,72
diff --git a/npc/008-2-8/mapflags.txt b/npc/008-2-8/mapflags.txt
new file mode 100644
index 000000000..2bdbedb90
--- /dev/null
+++ b/npc/008-2-8/mapflags.txt
@@ -0,0 +1 @@
+008-2-8 mapflag town
diff --git a/npc/008-2-9/_import.txt b/npc/008-2-9/_import.txt
new file mode 100644
index 000000000..aade14bd6
--- /dev/null
+++ b/npc/008-2-9/_import.txt
@@ -0,0 +1,5 @@
+// Map 008-2-9: Jack's Abode
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/008-2-9/_savepoints.txt",
+"npc/008-2-9/_warps.txt",
+"npc/008-2-9/mapflags.txt",
diff --git a/npc/008-2-9/_savepoints.txt b/npc/008-2-9/_savepoints.txt
new file mode 100644
index 000000000..e2aae5294
--- /dev/null
+++ b/npc/008-2-9/_savepoints.txt
@@ -0,0 +1,11 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-9: Jack's Abode saves
+008-2-9,26,31,0 script #save_008-2-9_26_31 NPC_SAVE_POINT,{
+ savepointparticle .map$, .x, .y, CURRENT_INN;
+ close;
+
+OnInit:
+ .distance = 2;
+ .sex = G_OTHER;
+ end;
+}
diff --git a/npc/008-2-9/_warps.txt b/npc/008-2-9/_warps.txt
new file mode 100644
index 000000000..7021feae8
--- /dev/null
+++ b/npc/008-2-9/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 008-2-9: Jack's Abode warps
+008-2-9,30,35,0 warp #008-2-9_30_35 0,0,008-1,72,69
diff --git a/npc/008-2-9/mapflags.txt b/npc/008-2-9/mapflags.txt
new file mode 100644
index 000000000..e637ae037
--- /dev/null
+++ b/npc/008-2-9/mapflags.txt
@@ -0,0 +1 @@
+008-2-9 mapflag town
diff --git a/npc/029-1/_import.txt b/npc/029-1/_import.txt
new file mode 100644
index 000000000..11097754e
--- /dev/null
+++ b/npc/029-1/_import.txt
@@ -0,0 +1,5 @@
+// Map 000-1: Drasil Island
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/029-1/_mobs.txt",
+"npc/029-1/_warps.txt",
+"npc/029-1/mapflags.txt",
diff --git a/npc/029-1/_mobs.txt b/npc/029-1/_mobs.txt
new file mode 100644
index 000000000..9bd9ea81c
--- /dev/null
+++ b/npc/029-1/_mobs.txt
@@ -0,0 +1,39 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-1: Drasil Island mobs
+000-1,28,49,6,9 monster Tortuga 1004,3,16000,120000
+000-1,58,118,34,14 monster Tortuga 1004,4,35000,300000
+000-1,71,95,4,12 monster Tortuga 1004,1,35000,300000
+000-1,52,92,4,17 monster Tortuga 1004,2,35000,300000
+000-1,37,66,11,5 monster Tortuga 1004,2,35000,120000
+000-1,42,41,9,16 monster Tortuga 1004,2,35000,120000
+000-1,87,37,12,11 monster Tortuga 1004,3,35000,120000
+000-1,44,75,2,1 monster Little Blub 1007,2,25000,120000
+000-1,61,64,7,10 monster Little Blub 1007,2,25000,120000
+000-1,62,25,10,4 monster Little Blub 1007,2,25000,120000
+000-1,87,69,4,3 monster Blub 1008,1,60000,120000
+000-1,85,33,2,3 monster Little Blub 1007,1,25000,120000
+000-1,85,58,14,9 monster Little Blub 1007,2,35000,120000
+000-1,48,61,9,6 monster Little Blub 1007,1,35000,120000
+000-1,28,48,3,5 monster Little Blub 1007,1,35000,120000
+000-1,35,50,0,1 monster Plushroom Field 1011,1,35000,150000
+000-1,54,115,0,1 monster Plushroom Field 1011,1,35000,150000
+000-1,63,80,4,2 monster Plushroom Field 1011,1,35000,150000
+000-1,54,64,0,2 monster Plushroom Field 1011,1,35000,150000
+000-1,78,58,4,5 monster Plushroom Field 1011,2,35000,150000
+000-1,71,62,1,1 monster Plushroom Field 1011,1,35000,150000
+000-1,32,116,8,9 monster Croc 1006,2,35000,300000
+000-1,63,31,10,3 monster Croc 1006,1,35000,300000
+000-1,76,68,1,1 monster Croc 1006,1,35000,300000
+000-1,52,92,4,17 monster Croc 1006,1,35000,300000
+000-1,71,77,4,4 monster Croc 1006,1,35000,300000
+000-1,0,0,0,0 monster Piou 1002,4,60000,15000
+000-1,78,115,0,0 monster Crocotree 1010,1,420000,240000
+000-1,57,104,0,0 monster Crocotree 1010,1,420000,240000
+000-1,39,112,0,0 monster Crocotree 1010,1,420000,240000
+000-1,67,93,0,0 monster Crocotree 1010,1,420000,240000
+000-1,53,77,0,0 monster Crocotree 1010,1,420000,240000
+000-1,64,63,0,0 monster Crocotree 1010,1,420000,240000
+000-1,31,69,0,0 monster Crocotree 1010,1,420000,240000
+000-1,44,44,0,0 monster Crocotree 1010,1,420000,240000
+000-1,70,33,0,0 monster Crocotree 1010,1,420000,240000
+000-1,84,66,0,0 monster Crocotree 1010,1,420000,240000
diff --git a/npc/029-1/_warps.txt b/npc/029-1/_warps.txt
new file mode 100644
index 000000000..237c27cb8
--- /dev/null
+++ b/npc/029-1/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 000-1: Drasil Island warps
+029-1,94,100,0 warp #000-1_94_100 0,0,000-2-0,21,28
diff --git a/npc/029-1/mapflags.txt b/npc/029-1/mapflags.txt
new file mode 100644
index 000000000..f2f0dab73
--- /dev/null
+++ b/npc/029-1/mapflags.txt
@@ -0,0 +1 @@
+029-1 mapflag town
diff --git a/npc/_import.txt b/npc/_import.txt
new file mode 100644
index 000000000..0923c29a9
--- /dev/null
+++ b/npc/_import.txt
@@ -0,0 +1,76 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+
+@include "npc/000-0-0/_import.txt"
+@include "npc/000-0-1/_import.txt"
+@include "npc/000-0/_import.txt"
+@include "npc/000-1/_import.txt"
+@include "npc/000-2-0/_import.txt"
+@include "npc/000-2-1/_import.txt"
+@include "npc/000-2-2/_import.txt"
+@include "npc/000-2-3/_import.txt"
+@include "npc/000-2-4/_import.txt"
+@include "npc/001-1/_import.txt"
+@include "npc/001-2-0/_import.txt"
+@include "npc/001-2-1/_import.txt"
+@include "npc/001-2-10/_import.txt"
+@include "npc/001-2-11/_import.txt"
+@include "npc/001-2-12/_import.txt"
+@include "npc/001-2-13/_import.txt"
+@include "npc/001-2-14/_import.txt"
+@include "npc/001-2-15/_import.txt"
+@include "npc/001-2-16/_import.txt"
+@include "npc/001-2-17/_import.txt"
+@include "npc/001-2-18/_import.txt"
+@include "npc/001-2-19/_import.txt"
+@include "npc/001-2-2/_import.txt"
+@include "npc/001-2-20/_import.txt"
+@include "npc/001-2-21/_import.txt"
+@include "npc/001-2-22/_import.txt"
+@include "npc/001-2-23/_import.txt"
+@include "npc/001-2-24/_import.txt"
+@include "npc/001-2-25/_import.txt"
+@include "npc/001-2-26/_import.txt"
+@include "npc/001-2-27/_import.txt"
+@include "npc/001-2-28/_import.txt"
+@include "npc/001-2-29/_import.txt"
+@include "npc/001-2-3/_import.txt"
+@include "npc/001-2-30/_import.txt"
+@include "npc/001-2-31/_import.txt"
+@include "npc/001-2-32/_import.txt"
+@include "npc/001-2-33/_import.txt"
+@include "npc/001-2-34/_import.txt"
+@include "npc/001-2-35/_import.txt"
+@include "npc/001-2-36/_import.txt"
+@include "npc/001-2-37/_import.txt"
+@include "npc/001-2-38/_import.txt"
+@include "npc/001-2-39/_import.txt"
+@include "npc/001-2-4/_import.txt"
+@include "npc/001-2-40/_import.txt"
+@include "npc/001-2-41/_import.txt"
+@include "npc/001-2-42/_import.txt"
+@include "npc/001-2-5/_import.txt"
+@include "npc/001-2-6/_import.txt"
+@include "npc/001-2-7/_import.txt"
+@include "npc/001-2-8/_import.txt"
+@include "npc/001-2-9/_import.txt"
+@include "npc/001-3-0/_import.txt"
+@include "npc/001-3-1/_import.txt"
+@include "npc/008-1/_import.txt"
+@include "npc/008-2-0/_import.txt"
+@include "npc/008-2-1/_import.txt"
+@include "npc/008-2-10/_import.txt"
+@include "npc/008-2-11/_import.txt"
+@include "npc/008-2-12/_import.txt"
+@include "npc/008-2-13/_import.txt"
+@include "npc/008-2-14/_import.txt"
+@include "npc/008-2-2/_import.txt"
+@include "npc/008-2-3/_import.txt"
+@include "npc/008-2-4/_import.txt"
+@include "npc/008-2-5/_import.txt"
+@include "npc/008-2-6/_import.txt"
+@include "npc/008-2-7/_import.txt"
+@include "npc/008-2-8/_import.txt"
+@include "npc/008-2-9/_import.txt"
+@include "npc/029-1/_import.txt"
+@include "npc/test/_import.txt"
+@include "npc/testbg/_import.txt"
diff --git a/npc/commands/debug-look.txt b/npc/commands/debug-look.txt
new file mode 100644
index 000000000..4bdcf84f1
--- /dev/null
+++ b/npc/commands/debug-look.txt
@@ -0,0 +1,102 @@
+function script BarberDebug {
+
+ function setGender {
+ //clear;
+ //setnpcdialogtitle l("Appearance Debug - Sex Change");
+ //mes l("Please choose the desired gender:");
+ //next;
+ //menuint
+ // l("Male"), G_MALE,
+ // l("Female"), G_FEMALE,
+ // l("Non-binary"), G_OTHER;
+
+ //Sex = @menuret; // FIXME: make this work like in tmwAthena
+ //return;
+
+
+ // ^ Future code, Doesn't work yet
+ closedialog;
+ changecharsex;
+ }
+ function setStyle {
+ clear;
+ setnpcdialogtitle l("Appearance Debug - Barber");
+ mes l("Hair style") + ": " + getlook(LOOK_HAIR);
+ next;
+ mes l("Please enter the desired style") + " (1-255)";
+ input .@h, 1, 0xFF;
+ setlook LOOK_HAIR, max(1, min(0xFF, .@h));
+ return;
+ }
+ function setColor {
+ clear;
+ setnpcdialogtitle l("Appearance Debug - Barber");
+ mes l("Hair color") + ": " + getlook(LOOK_HAIR_COLOR);
+ next;
+ mes l("Please enter the desired color") + " (0-255)";
+ input .@h, 0, 0xFF;
+ setlook LOOK_HAIR_COLOR, max(0, min(0xFF, .@h));
+ return;
+ }
+ function setRace {
+ clear;
+ setnpcdialogtitle l("Appearance Debug - Race");
+ mes l("Race") + ": " + Class;
+ next;
+ mes l("Please enter the desired race") + " (0-32767)";
+ input .@r, 0, 0x7FFF;
+ jobchange max(0, min(0x7FFF, .@r));
+ return;
+ }
+
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Appearance Debug");
+ mes l("This menu allows you to customize your appearance.");
+ mes "";
+
+ mes "---";
+ mes l("Gender") + ": " + Sex;
+ mes l("Hair style") + ": " + getlook(LOOK_HAIR);
+ mes l("Hair color") + ": " + getlook(LOOK_HAIR_COLOR);
+ mes l("Race") + ": " + Class;
+ mes "---";
+
+ next;
+ mes l("What do you want to change?");
+ select
+ menuimage("actions/edit", l("Gender") + " [" + l("Requires logout") + "]"),
+ menuimage("actions/edit", l("Hair style")),
+ menuimage("actions/edit", l("Hair color")),
+ menuimage("actions/edit", l("Race")),
+ rif(getarg(0,0), menuimage("actions/back", l("Return to Debug menu")));
+
+ switch (@menu)
+ {
+ case 1: setGender; break;
+ case 2: setStyle; break;
+ case 3: setColor; break;
+ case 4: setRace; break;
+ case 5: return;
+ }
+ } while (1);
+}
+
+
+
+- script @look 32767,{
+ end;
+
+OnCall:
+ if (!debug && !is_dev())
+ {
+ end;
+ }
+ BarberDebug;
+ closedialog;
+ end;
+
+OnInit:
+ bindatcmd "look", "@look::OnCall", 0, 99, 0;
+}
diff --git a/npc/commands/debug-preset.txt b/npc/commands/debug-preset.txt
new file mode 100644
index 000000000..40f612614
--- /dev/null
+++ b/npc/commands/debug-preset.txt
@@ -0,0 +1,246 @@
+// Preset / routine system
+// Author:
+// gumi
+// Description:
+// allows to execute multiple commands in a single step
+// to ease testing and debugging
+//
+// usage: @pre [options] <instruction>[, <instruction>...]
+// usage: DoRoutine "[options] <instruction>[, <instruction>...]";
+//
+// example: @pre -s a22 v14
+// resets all stats, gives 22 agi, gives 14 vit
+//
+// ^ actual documentation may come one day, when I feel like it
+// *hides*
+
+function script DoRoutine {
+
+ function parsev {
+ // parsev(base, patterns{, min{, max}}) => value
+ .@value = getarg(0, 0);
+ .@raw$ = getarg(1, "");
+ .@patterns = explode(.@patterns$, .@raw$, "|");
+
+ for (.@pattern = 0; .@pattern < .@patterns; ++.@pattern)
+ {
+ .@pattern$ = .@patterns$[.@pattern];
+ .@len = getstrlen(.@pattern$);
+
+ if (charat(.@pattern$, 0) == "=" && .@len >= 2)
+ {
+ .@value = atoi(delchar(.@pattern$, 0));
+ break;
+ }
+
+ else if (charat(.@pattern$, 0) == "+" && .@len >= 2)
+ {
+ if (charat(.@pattern$, 1) == "+" && getargcount() >= 4)
+ .@value = getarg(3);
+ else
+ .@value += atoi(delchar(.@pattern$, 0));
+ }
+
+ else if (charat(.@pattern$, 0) == "-" && .@len >= 2)
+ {
+ if (charat(.@pattern$, 1) == "-" && getargcount() >= 3)
+ .@value = getarg(2);
+ else
+ .@value -= atoi(delchar(.@pattern$, 0));
+ }
+
+ else if (charat(.@pattern$, 0) == ">" && .@len >= 2)
+ {
+ if (charat(.@pattern$, 1) == "=" && .@len >= 3)
+ .@value = max(atoi(substr(.@pattern$, 2, .@len - 1)), .@value);
+ else
+ .@value = max(atoi(delchar(.@pattern$, 0)) + 1, .@value);
+ }
+
+ else if (charat(.@pattern$, 0) == "<" && .@len >= 2)
+ {
+ if (charat(.@pattern$, 1) == "=" && .@len >= 3)
+ .@value = min(atoi(substr(.@pattern$, 2, .@len - 1)), .@value);
+ else
+ .@value = min(atoi(delchar(.@pattern$, 0)) - 1, .@value);
+ }
+
+ else if (.@len >= 1)
+ {
+ .@value = atoi(.@pattern$);
+ break;
+ }
+ }
+
+ if (getargcount() >= 3)
+ .@value = max(getarg(2), .@value);
+
+ if (getargcount() >= 4)
+ .@value = min(getarg(3), .@value);
+
+ return .@value;
+ }
+
+ .@routine$ = strip(getarg(0,""));
+ .@m = explode(.@routine$[0], .@routine$, " "); // prep the base array
+
+ if (charat(.@routine$[0], 0) == "-")
+ {
+ if (compare(.@routine$[0], "t"))
+ {
+ clearitem;
+ }
+
+ if (compare(.@routine$[0], "e"))
+ {
+ nude;
+ }
+
+ if (compare(.@routine$[0], "k"))
+ {
+ resetskill;
+ }
+
+ if (compare(.@routine$[0], "s"))
+ {
+ resetstatus;
+ }
+
+ if (compare(.@routine$[0], "x"))
+ {
+ resetlvl 2;
+ }
+
+ if (compare(.@routine$[0], "q"))
+ {
+ //doevent "::OnGlobalQuestReset"; // executes in all quest npcs // FIXME: maybe have a `resetquest` buildin?
+ // FIXME: ^ need a buildin that can run *right now* instead of on script end
+ }
+
+ if (compare(.@routine$[0], "n"))
+ {
+ closeclientdialog;
+ }
+
+ .@i = 1;
+ }
+
+ for (; .@i < .@m; ++.@i)
+ {
+ .@type = ord(charat(strip(.@routine$[.@i]), 0));
+
+ if (.@type > 0)
+ {
+ .@raw$ = delchar(.@routine$[.@i], 0);
+ .@args = explode(.@args$, .@raw$, ",");
+ .@a = atoi(.@args$[0]);
+ .@b = atoi(.@args$[1]);
+ .@c = atoi(.@args$[2]);
+ .@d = atoi(.@args$[3]);
+ .@e = atoi(.@args$[4]);
+
+ switch (.@type)
+ {
+ case 97: /* a => Agi */
+ .@base = readparam(bAgi);
+ statusup2 bAgi, parsev(.@base, .@args$[0], 1, 99) - .@base;
+ break;
+ /* (b) */
+ case 99: /* c => job */
+ jobchange max(0, min(6, .@a));
+ break;
+ case 100: /* d => Dex */
+ .@base = readparam(bDex);
+ statusup2 bDex, parsev(.@base, .@args$[0], 1, 99) - .@base;
+ break;
+ case 101: /* e => equip */
+ equip max(1, min(32767, .@a));
+ break;
+ /* (f) */
+ /* (g) => gender (reserved) */
+ /* (h) */
+ case 105: /* i => Int */
+ .@base = readparam(bInt);
+ statusup2 bInt, parsev(.@base, .@args$[0], 1, 99) - .@base;
+ break;
+ /* (j) */
+ case 107: /* k => skill */
+ .@k = max(1, min(32767, .@a));
+ skill .@k, parsev(getskilllv(.@k), .@args$[1], 0, 10), 0;
+ break;
+ case 108: /* l => luk */
+ .@base = readparam(bLuk);
+ statusup2 bLuk, parsev(.@base, .@args$[0], 1, 99) - .@base;
+ break;
+ /* (m) => mercenary (reserved) */
+ /* (n) => talk to npc (reserved) */
+ /* (o) */
+ case 112: /* p => pet */
+ makepet max(1002, min(32767, .@a));
+ break;
+ case 113: /* q => quest */
+ .@q = max(0, min(32767, .@a));
+ setq .@q, parsev(getq(.@q), .@args$[1]),
+ parsev(getq2(.@q), .@args$[2]),
+ parsev(getq3(.@q), .@args$[3]),
+ parsev(getqtime(.@q), .@args$[4]);
+ break;
+ /* (r) */
+ case 115: /* s => Str */
+ .@base = readparam(bStr);
+ statusup2 bStr, parsev(.@base, .@args$[0], 1, 99) - .@base;
+ break;
+ case 116: /* t => item */
+ .@t = max(1, min(32767, .@a));
+ .@c = countitem(.@t);
+ .@v = parsev(.@c, .@args$[1], 0, 32767);
+ if (.@c > .@v)
+ delitem .@t, .@c - .@v;
+ else if (.@c < .@v)
+ getitem .@t, .@v - .@c;
+ break;
+ /* (u) */
+ case 118: /* v => vit */
+ .@base = readparam(bVit);
+ statusup2 bVit, parsev(.@base, .@args$[0], 1, 99) - .@base;
+ break;
+ case 119: /* w => warp */
+ warp .@args$[0], .@b, .@c;
+ break;
+ case 120: /* x => base level */
+ BaseLevel = parsev(BaseLevel, .@args$[0], 1, 99);
+ BaseExp = parsev(BaseExp, .@args$[1], 0);
+ break;
+ case 121: /* y => job level */
+ JobLevel = parsev(JobLevel, .@args$[0], 1, 255);
+ JobExp = parsev(JobExp, .@args$[1], 0);
+ break;
+ case 122: /* z => zeny */
+ Zeny = parsev(Zeny, .@args$[0], 0, 0x7FFFFFFE);
+ BankVault = parsev(BankVault, .@args$[1], 0, MAX_BANK_ZENY);
+ break;
+ }
+ }
+ }
+
+ return;
+}
+
+- script @pre 32767,{
+ end;
+
+OnCall:
+ if (!debug && !is_admin())
+ {
+ end;
+ }
+ if (.@atcmd_parameters$[0] != "")
+ {
+ .@atcmd_parameters$[0] = implode(.@atcmd_parameters$[0], " ");
+ }
+ DoRoutine strip(.@atcmd_parameters$[0]);
+ end;
+
+OnInit:
+ bindatcmd "pre", "@pre::OnCall", 0, 99, 0;
+}
diff --git a/npc/commands/debug-quest.txt b/npc/commands/debug-quest.txt
new file mode 100644
index 000000000..889c988d4
--- /dev/null
+++ b/npc/commands/debug-quest.txt
@@ -0,0 +1,157 @@
+function script GlobalQuestDebug {
+
+ function qDebugShip {
+ function qDebugGugli {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug") + " - " + l("Prologue") + " - Gugli";
+ mes l("This menu gives access to quest debug menus for @@ quest subquests.", "Gugli");
+ next;
+ mes l("Please select a quest:");
+
+ menuint
+ menuimage("actions/back", l("Go back")), -1,
+ l("Gugli (main quest)"), ShipQuests_Gugli,
+ "Ale", ShipQuests_Ale,
+ "Astapolos", ShipQuests_Astapolos,
+ "Gulukan", ShipQuests_Gulukan,
+ "Jalad", ShipQuests_Jalad,
+ "Q'Muller", ShipQuests_QMuller,
+ "Tibbo", ShipQuests_Tibbo;
+
+ switch (@menuret)
+ {
+ case -1: return;
+ default: callfunc "QuestDebug" + @menuret;
+ }
+ } while (1);
+ }
+
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug") + " - " + l("Prologue");
+ mes l("This menu gives access to quest debug menus for @@ quests.", l("Prologue"));
+ next;
+ mes l("Please select a quest:");
+
+ menuint
+ menuimage("actions/back", l("Go back")), -1,
+ "Julia", ShipQuests_Julia,
+ "Arpan", ShipQuests_Arpan,
+ "Alige", ShipQuests_Alige,
+ "Peter", ShipQuests_Peter,
+ "Nard", ShipQuests_Nard,
+ l("Knife"), ShipQuests_Knife,
+ l("Money"), ShipQuests_ArpanMoney,
+ l("Door"), ShipQuests_Door,
+ "Couwan", ShipQuests_Couwan,
+ l("Treasure Chest"), ShipQuests_TreasureChest,
+ "Gugli", ShipQuests_Gugli,
+ "Gado", ShipQuests_ChefGado;
+
+ switch (@menuret)
+ {
+ case 16: qDebugGugli; break;
+ case -1: return;
+ default: callfunc "QuestDebug" + @menuret;
+ }
+ } while (1);
+ }
+
+ function qDebugArtis {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug") + " - " + l("Artis");
+ mes l("This menu gives access to quest debug menus for @@ quests.", "Artis");
+ next;
+ mes l("Please select a quest:");
+
+ menuint
+ menuimage("actions/back", l("Go back")), -1,
+ l("Lazy Brother"), ArtisQuests_LazyBrother,
+ l("Urchin"), ArtisQuests_Urchin,
+ l("Catching a piou"), ArtisQuests_CatchPiou,
+ "Eugene (" + l("fisherman") + ")", ArtisQuests_Fishman,
+ "Q'Onan", ArtisQuests_QOnan,
+ "Enora", ArtisQuests_Enora,
+ "Fexil", ArtisQuests_Fexil,
+ "Lloyd", ArtisQuests_Lloyd,
+ l("Mona's dad"), ArtisQuests_MonaDad,
+ l("Artis legion progress"), Artis_Legion_Progress;
+
+ switch (@menuret)
+ {
+ case -1: return;
+ default: callfunc "QuestDebug" + @menuret;
+ }
+ } while (1);
+ }
+
+ function qDebugGeneral {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug") + " - " + l("Other");
+ mes l("This menu gives access to quest debug menus for @@ quests.", strtolower(l("Other")));
+ next;
+ mes l("Please select a quest:");
+
+ menuint
+ menuimage("actions/back", l("Go back")), -1,
+ l("Cookies"), General_Cookies,
+ "Rumly", General_Rumly,
+ l("Narrator"), General_Narrator,
+ "Janus", General_Janus;
+
+ switch (@menuret)
+ {
+ case -1: return;
+ default: callfunc "QuestDebug" + @menuret;
+ }
+ } while (1);
+ }
+
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes l("This menu gives access to all quest debug menus.");
+ next;
+ mes l("Please select a category:");
+
+ select
+ l("Prologue"),
+ "Artis",
+ l("Other"),
+ rif(getarg(0,0), menuimage("actions/back", l("Return to Debug menu")));
+
+ switch (@menu)
+ {
+ case 1: qDebugShip; break;
+ case 2: qDebugArtis; break;
+ case 3: qDebugGeneral; break;
+ case 4: return;
+ }
+ } while (1);
+}
+
+
+
+- script @qdebug 32767,{
+ end;
+
+OnCall:
+ if (!debug && !is_trusted())
+ {
+ end;
+ }
+ GlobalQuestDebug;
+ closedialog;
+ end;
+
+OnInit:
+ bindatcmd "qdebug", "@qdebug::OnCall", 0, 99, 0;
+}
diff --git a/npc/commands/debug-skill.txt b/npc/commands/debug-skill.txt
new file mode 100644
index 000000000..2e5393a49
--- /dev/null
+++ b/npc/commands/debug-skill.txt
@@ -0,0 +1,81 @@
+function script GlobalSkillDebug {
+
+ function modifySkill {
+
+ function setSkill {
+ clear;
+ mes l("Enter desired skill level:");
+ input .@y;
+ skill getarg(0,1), max(0, min(10, .@y)), 0;
+ return;
+ }
+
+ setnpcdialogtitle l("Skill Debug - Modify Skill");
+ .@k = getarg(0,1);
+ .@v = getskilllv(.@k);
+ select
+ menuimage("actions/abort", l("Abort")),
+ rif(.@v > 0, menuimage("actions/remove", l("Remove this skill"))),
+ rif(.@v < 10, menuimage("actions/raise", l("Raise this skill"))),
+ rif(.@v > 0, menuimage("actions/lower", l("Lower this skill"))),
+ menuimage("actions/edit", l("Set the level manually")),
+ menuimage("actions/back", l("Return to skill debug menu"));
+
+ switch (@menu)
+ {
+ case 2: skill .@k, 0, 0; break;
+ case 3: skill .@k, min(10, .@v + 1), 0; break;
+ case 4: skill .@k, max(0, .@v - 1), 0; break;
+ case 5: setSkill .@k; break;
+ }
+
+ return;
+ }
+
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Skill Debug");
+ mes l("This menu allows you to change your skills.");
+ mes "";
+
+ mes "---";
+ // FIXME: maybe get skills from an array or `getskilllist;` <= would need a `getskillinfo()` buildin though
+ mes "NV_BASIC: " + getskilllv(NV_BASIC);
+ mes "---";
+
+ mes "";
+ mes l("Which skill do you wish to change?");
+ next;
+
+ menuint
+ "NV_BASIC", NV_BASIC,
+ rif(getarg(0,0), menuimage("actions/back", l("Return to Debug menu"))), -1;
+
+ switch (@menuret)
+ {
+ case -1: return;
+ }
+
+ modifySkill @menuret;
+
+ } while (1);
+}
+
+
+
+- script @sdebug 32767,{
+ end;
+
+OnCall:
+ if (!debug && !is_admin())
+ {
+ end;
+ }
+ GlobalSkillDebug;
+ closedialog;
+ end;
+
+OnInit:
+ bindatcmd "sdebug", "@sdebug::OnCall", 0, 99, 0;
+}
diff --git a/npc/commands/debug.txt b/npc/commands/debug.txt
new file mode 100644
index 000000000..193abb5b2
--- /dev/null
+++ b/npc/commands/debug.txt
@@ -0,0 +1,143 @@
+function script GlobalDebugMenu {
+ function resetAll {
+ function doReset {
+ resetstatus;
+ resetskill;
+ resetlvl 1;
+ dispbottom l("Reset done!");
+ if (getarg(0,0) == 3)
+ {
+ closedialog;
+ doevent "::OnGlobalQuestReset"; // executes in all quest npcs // FIXME: maybe have a `resetquest` buildin?
+ Zeny = 0;
+ BankVault = 0;
+ clearitem;
+ warp "000-0", 0, 0; // starting point
+ end; // script must end for doevent to execute
+ }
+ return;
+ }
+ clear;
+ setnpcdialogtitle l("Debug - Reset");
+ mes l("What do you want to reset?");
+ select
+ menuimage("actions/abort", l("Abort")),
+ menuimage("actions/reset", l("Reset stats, skills, level")),
+ menuimage("actions/nuke", l("Reset EVERYTHING")),
+ menuimage("actions/back", l("Return to Debug menu"));
+
+ switch (@menu)
+ {
+ case 2:
+ case 3: doReset @menu;
+ }
+
+ return;
+ }
+
+ function changeLevel {
+ clear;
+ setnpcdialogtitle l("Debug - Change level");
+ mes l("To change your base level, use this command:");
+ mes "";
+ mes " " + col("@blvl <" + l("delta") + ">", 3);
+ next;
+ mes l("Example:");
+ mes "@blvl 50";
+ mes " " + l("Raises your base level by 50");
+ mes "@blvl -50";
+ mes " " + l("Reduces your base level by 50");
+ next;
+ mes l("To change your job level, use this command:");
+ mes "";
+ mes " " + col("@jlvl <" + l("delta") + ">", 3);
+ next;
+ mes l("Example:");
+ mes "@jlvl 50";
+ mes " " + l("Raises your job level by 50");
+ mes "@jlvl -50";
+ mes " " + l("Reduces your job level by 50");
+ next;
+ return;
+ }
+ function changeStats {
+ clear;
+ setnpcdialogtitle l("Debug - Change stats");
+ mes l("To change your stats, use these commands:");
+ mes "";
+ mes " " + col("@str <" + l("delta") + ">", 3);
+ mes " " + col("@agi <" + l("delta") + ">", 3);
+ mes " " + col("@vit <" + l("delta") + ">", 3);
+ mes " " + col("@int <" + l("delta") + ">", 3);
+ mes " " + col("@dex <" + l("delta") + ">", 3);
+ mes " " + col("@luk <" + l("delta") + ">", 3);
+ next;
+ mes l("Example:");
+ mes "@int 50";
+ mes " " + l("Raises your Int by 50");
+ mes "@int -50";
+ mes " " + l("Reduces your Int by 50");
+ next;
+ mes l("If you simply wish to get 99 in all stats:");
+ mes "";
+ mes " " + col("@allstats", 3);
+ next;
+ mes l("If you wish to reset your stats:");
+ mes "";
+ mes " " + col("@streset", 3);
+ next;
+ return;
+ }
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Debug");
+ mes l("This menu allows you to modify your account data.");
+ mes "";
+ mes l("What do you want to do?");
+ select
+ menuimage("actions/manage", l("Change my level")),
+ menuimage("actions/manage", l("Change my stats")),
+ menuimage("actions/manage", l("Change my skills")),
+ menuimage("actions/manage", l("Change my appearance")),
+ menuimage("actions/add", l("Create items")),
+ menuimage("actions/add", l("Get money")),
+ menuimage("actions/edit", l("Change my quests")),
+ menuimage("actions/reset", l("Reset")),
+ rif(getarg(0,0), menuimage("actions/home", l("Return to Super Menu")));
+
+ .@c = getarg(0,0) ? 2 : 1;
+
+ switch (@menu)
+ {
+ case 1: changeLevel; break;
+ case 2: changeStats; break;
+ case 3: GlobalSkillDebug .@c; break;
+ case 4: BarberDebug .@c; break;
+ case 5: closedialog; clientcommand "createitems"; end;
+ case 6: Zeny = 0x7FFFFFFE; break;
+ case 7: GlobalQuestDebug .@c; break;
+ case 8: resetAll; break;
+ case 9: return;
+ }
+ } while(1);
+}
+
+
+
+- script @debug 32767,{
+ end;
+
+OnCall:
+ if (!debug && !is_admin())
+ {
+ end;
+ }
+ GlobalDebugMenu;
+ closedialog;
+ end;
+
+OnInit:
+ bindatcmd "debug", "@debug::OnCall", 0, 99, 0;
+ // TODO / FIXME: add a @test command that opens the help window for test-server
+}
diff --git a/npc/commands/event.txt b/npc/commands/event.txt
new file mode 100644
index 000000000..db98bcf29
--- /dev/null
+++ b/npc/commands/event.txt
@@ -0,0 +1,57 @@
+function script GlobalEventMenu {
+
+ function rateManagement {
+ clear;
+ mes l("To get the current rate:");
+ mes col(" @exprate", 7);
+ next;
+ mes l("To set the exp rate:");
+ mes col(" @exprate ##Brate##b hours", 7);
+ next;
+ mes l("To reset back to normal:");
+ mes col(" @exprate default", 7); // note to translators: any non-numerical value will reset so "default" is safe to translate
+ next;
+ return;
+ }
+
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Event Management");
+ mes l("This menu allows you to manage events and gives access to event-related tools.");
+ mes "";
+ mes l("What do you want to access?");
+
+ select
+ l("Rate management"),
+ rif(getarg(0,0), menuimage("actions/home", l("Return to Super Menu")));
+
+ //.@c = getarg(0,0) ? 2 : 1; // 1 = back to event menu, 2 = back to super menu
+
+ switch (@menu)
+ {
+ case 1: rateManagement; break;
+ default: return;
+ }
+
+ } while (true);
+}
+
+
+
+- script @event 32767,{
+ end;
+
+OnCall:
+ if (!is_evtc())
+ {
+ end;
+ }
+
+ GlobalEventMenu;
+ closedialog;
+ end;
+
+OnInit:
+ bindatcmd "event", "@event::OnCall", 0, 99, 0;
+}
diff --git a/npc/commands/motd.txt b/npc/commands/motd.txt
new file mode 100644
index 000000000..9a9c702e1
--- /dev/null
+++ b/npc/commands/motd.txt
@@ -0,0 +1,193 @@
+function script displayMOTD {
+ .@size = getvariableofnpc(.size, "@motd");
+ .@dsize = getvariableofnpc(.dsize, "@motd");
+
+ // git stuff and such
+ if (debug)
+ {
+ for (.@i = 0; .@i < .@dsize; ++.@i)
+ {
+ dispbottom $@Debug_Messages$[.@i]; // FIXME: send this to the Debug tab instead
+ }
+
+ if (.@dsize > 0)
+ dispbottom "---";
+ }
+
+ // generic MOTD
+ for (.@i = 0; .@i < .@size; ++.@i)
+ {
+ dispbottom $MOTD_Messages$[.@i];
+ }
+
+ return;
+}
+
+function script MOTDConfig {
+
+ function toggleMOTD {
+ $MOTD_Disabled = !($MOTD_Disabled);
+ // FIXME: log to GM log
+ }
+
+ function addNewLine {
+ clear;
+ mes l("Please enter the new line.");
+ input .@s$;
+ .@s$ = strip(.@s$);
+ if (.@s$ != "")
+ {
+ .@size = getvariableofnpc(.size, "@motd");
+ $MOTD_Messages$[.@size] = .@s$;
+ set getvariableofnpc(.size, "@motd"), getarraysize($MOTD_Messages$);
+ // FIXME: log to GM log
+ }
+ }
+
+ function modifyLine {
+
+ function removeLine {
+ .@l = getarg(0);
+ deletearray $MOTD_Messages$[.@l], 1; // remove and shift
+ mes l("Line @@ has been removed.", .@l);
+ set getvariableofnpc(.size, "@motd"), getarraysize($MOTD_Messages$);
+ // FIXME: log to GM log
+ }
+
+ function moveUp {
+ .@l = getarg(0);
+ .@top$ = $MOTD_Messages$[.@l - 1];
+ $MOTD_Messages$[.@l - 1] = $MOTD_Messages$[.@l];
+ $MOTD_Messages$[.@l] = .@top$;
+ }
+
+ function moveDown {
+ .@l = getarg(0);
+ .@bottom$ = $MOTD_Messages$[.@l + 1];
+ $MOTD_Messages$[.@l + 1] = $MOTD_Messages$[.@l];
+ $MOTD_Messages$[.@l] = .@bottom$;
+ }
+
+ function editLine {
+ .@l = getarg(0);
+ clear;
+ mes l("Old line:");
+ mes "---";
+ mes $MOTD_Messages$[.@l];
+ mes "---";
+ mes "";
+ mes l("Enter new line:");
+ next;
+ input .@s$;
+ .@s$ = strip(.@s$);
+ if (.@s$ != "")
+ {
+ $MOTD_Messages$[.@l] = .@s$;
+ // FIXME: log to GM log
+ }
+ }
+
+ .@max = (getarg(0) - 1);
+
+ do
+ {
+ mes l("Enter line number:");
+ next;
+ input .@n;
+ if ($MOTD_Messages$[.@n] != "")
+ {
+ clear;
+ mes l("line @@: @@", .@n, $MOTD_Messages$[.@n]);
+ next;
+ select
+ menuimage("actions/back", l("Modify another line")),
+ menuimage("actions/remove", l("Remove this line")),
+ menuimage("actions/edit", l("Modify this line")),
+ rif(.@n > 0, menuimage("actions/raise", l("Move this line up"))),
+ rif(.@n < .@max, menuimage("actions/lower", l("Move this line down"))),
+ menuimage("actions/home", l("Return to main menu"));
+
+ switch (@menu)
+ {
+ case 2: removeLine .@n; return;
+ case 3: editLine .@n; return;
+ case 4: moveUp .@n; return;
+ case 5: moveDown .@n; return;
+ case 6: return;
+ }
+ }
+ } while (1);
+ }
+
+ do
+ {
+ clear;
+ setnpcdialogtitle l("MOTD Config");
+ mes l("This menu allows you to modify the generic message that is sent to players when they log in.");
+ mes "";
+
+ mes "---";
+ .@size = getvariableofnpc(.size, "@motd");
+ for (.@i = 0; .@i < .@size; ++.@i)
+ {
+ mes l("line @@: @@", .@i, $MOTD_Messages$[.@i]);
+ }
+ if (.@size == 0)
+ {
+ mes "(" + l("no active MOTD") + ")";
+ }
+ mes "---";
+ .@d = $MOTD_Disabled;
+ mes l("Enabled: @@", (.@d ? l("no") : l("yes")));
+ next;
+
+ select
+ menuimage("actions/toggle", (.@d ? l("Enable") : l("Disable"))),
+ menuimage("actions/add", l("Add a new line")),
+ rif(.@size, menuimage("actions/manage", l("Modify, move, or remove a line"))),
+ rif(.@size, menuimage("actions/test", l("Test MOTD"))),
+ rif(getarg(0,0), menuimage("actions/home", l("Return to Super Menu")));
+
+ switch (@menu)
+ {
+ case 1: toggleMOTD; break;
+ case 2: addNewLine; break;
+ case 3: modifyLine .@size; break;
+ case 4: displayMOTD; break;
+ default: return;
+ }
+ } while (1);
+}
+
+
+
+- script @motd 32767,{
+ end;
+
+OnCall:
+ if (!is_dev())
+ {
+ end;
+ }
+
+ MOTDConfig;
+ closedialog;
+ end;
+
+OnPCLoginEvent:
+ if ($MOTD_Disabled < 1)
+ {
+ displayMOTD;
+ }
+ if (debug)
+ {
+ dispbottom "##7<<##B @@help://test-server|" + col(l("Click here for instructions on how to use the test server."),6) + "@@ ##7>>";
+ }
+ end;
+
+OnInit:
+ MOTD_debug_text;
+ .size = getarraysize($MOTD_Messages$);
+ .dsize = getarraysize($@Debug_Messages$);
+ bindatcmd "motd", "@motd::OnCall", 0, 99, 0;
+}
diff --git a/npc/commands/music.txt b/npc/commands/music.txt
new file mode 100644
index 000000000..e794060fc
--- /dev/null
+++ b/npc/commands/music.txt
@@ -0,0 +1,46 @@
+// @music atcommand
+// changes the music for all players on the map
+//
+// group lv: 2
+// group char lv: 99
+// log: True
+//
+// usage:
+// @music <short name>
+//
+// example:
+// @music fun
+
+- script @music 32767,{
+ end;
+
+OnCall:
+ if (!is_evtc())
+ {
+ end;
+ }
+
+ // TODO: tmw-like argv splitter
+ getmapxy .@map$, .@void, .@void, UNITTYPE_PC; // get map
+
+ .@key$ = .@atcmd_parameters$[0];
+ .@m$ = htget(.hash, .@key$, "Not found");
+
+ if (.@m$ == "Not found")
+ {
+ .@m$ = implode(.@atcmd_parameters$[0], " ");
+ }
+
+ changemusic .@map$, .@m$ + ".ogg";
+ end;
+
+OnInit:
+ bindatcmd "music", "@music::OnCall", 0, 99, 1;
+
+ .hash = htnew; // create hashtable
+ htput(.hash, "forest", "bartk - in the forest of the birches");
+ htput(.hash, "adventure", "bartk - the adventure begins");
+ htput(.hash, "fun", "eric matyas - ghoulish fun");
+ htput(.hash, "surreal", "eric matyas - surreal place");
+ htput(.hash, "ocean", "ezili - ocean sounds");
+}
diff --git a/npc/commands/rate-management.txt b/npc/commands/rate-management.txt
new file mode 100644
index 000000000..995ef940f
--- /dev/null
+++ b/npc/commands/rate-management.txt
@@ -0,0 +1,107 @@
+- script @exprate 32767,{
+ end;
+
+ function rateCleanUp {
+ stopnpctimer;
+ .hours = 0;
+ .max_hours = 0;
+ .current_rate = .original_exp_rate;
+ setbattleflag("base_exp_rate", .original_exp_rate);
+ setbattleflag("quest_exp_rate", .original_quest_rate);
+ charcommand("@reloadmobdb"); // this is on purpose (callable without RID)
+ charcommand("@reloadquestdb");
+ }
+
+ function remainingTime {
+ .@total_seconds = (3600 * .max_hours);
+ .@seconds_elapsed = (3600 * .hours) + (getnpctimer(0) / 1000);
+ .@seconds_remaining = max(1, .@total_seconds - .@seconds_elapsed);
+ return FuzzyTime(time_from_seconds(.@seconds_remaining), 2, 2);
+ }
+
+OnCall:
+ if (!is_evtc())
+ {
+ end;
+ }
+
+ .@special$ = strip(.@atcmd_parameters$[0]); // special value
+ .@new_rate = min(atoi(.@special$), 1000); // or just a regular integer
+ .@hours = min(0x7FFFFFFE, max(1, atoi(strip(.@atcmd_parameters$[1])))); // number of hours
+
+ if (.@new_rate > 0)
+ {
+ // set new exp rate
+ .hours = 0;
+ .max_hours = .@hours;
+ .current_rate = .@new_rate;
+ setbattleflag("base_exp_rate", .@new_rate);
+ setbattleflag("quest_exp_rate", .@new_rate);
+ charcommand("@reloadmobdb");
+ charcommand("@reloadquestdb");
+ initnpctimer; // start counting
+
+ dispbottom l("You successfully set the exp rate to @@%. It will reset to @@% (default value) in @@.",
+ .@new_rate, .original_exp_rate, FuzzyTime(time_from_hours(.max_hours), 2, 2));
+ dispbottom l("You can also manually stop it at any time with: @exprate default");
+ }
+
+ else if (.@new_rate == 0 && .@special$ == "")
+ {
+ // get current exp rate
+ if (.current_rate == .original_exp_rate)
+ {
+ dispbottom l("Current exp rate is set to @@% (default value).", .current_rate);
+ }
+
+ else
+ {
+ dispbottom l("Current exp rate is set to @@%, and will reset to @@% (default value) in @@.",
+ .current_rate, .original_exp_rate, remainingTime());
+
+ dispbottom l("If you meant to reset the exp rate to its default value: @exprate default");
+ }
+ }
+
+ else
+ {
+ // reset
+ rateCleanUp;
+ dispbottom l("Exp rate has been reset to @@% (default value).",
+ .original_exp_rate);
+ }
+
+ end;
+
+OnTimer3600000:
+ // runs every hour
+ if (++.hours == .max_hours)
+ {
+ rateCleanUp;
+ end;
+ }
+ initnpctimer;
+ end;
+
+OnPCLoginEvent:
+ if (.max_hours > 0)
+ {
+ dispbottom col(l("Exp rate is set to @@% for the next @@.",
+ .current_rate, remainingTime()), 6);
+ }
+ end;
+
+OnInit:
+ bindatcmd "exprate", "@exprate::OnCall", 0, 99, 1; // change exp rate
+
+ // WARNING: using @reloadscript will change the "original" value
+ .original_exp_rate = getbattleflag("base_exp_rate");
+ .original_quest_rate = getbattleflag("quest_exp_rate");
+ .current_rate = .original_exp_rate;
+
+ // XXX: maybe in the future:
+ //.original_item_rate = getbattleflag("item_rate_common");
+ //.original_job_rate = getbattleflag("base_job_rate");
+ //.original_pk_mode = getbattleflag("pk_mode");
+ //.original_death_penalty = getbattleflag("death_penalty_type");
+}
diff --git a/npc/commands/scheduled-broadcasts.txt b/npc/commands/scheduled-broadcasts.txt
new file mode 100644
index 000000000..6bfbf2935
--- /dev/null
+++ b/npc/commands/scheduled-broadcasts.txt
@@ -0,0 +1,225 @@
+function script StoneBoard {
+
+ function setMessage {
+ do
+ {
+ clear;
+ mes l("Please enter the message:");
+ next;
+ input .@msg$;
+ .@msg$ = strip(.@msg$);
+ if (.@msg$ != "")
+ {
+ return .@msg$;
+ }
+ mes l("The message cannot be empty");
+ next;
+ } while (1);
+ }
+
+ function setInterval {
+ clear;
+ mes l("Please select the interval:");
+ next;
+ menuint
+ l("Every 1 hour"), 1,
+ l("Every 3 hours"), 3,
+ l("Every 5 hours"), 5,
+ l("Every 6 hours"), 6,
+ l("Every 12 hours"), 12,
+ l("Every 24 hours"), 24,
+ l("Never (only on login)"), 0;
+
+ return @menuret;
+ }
+
+ function setMaxRep {
+ if (getarg(0,0) == 0)
+ {
+ return 0;
+ }
+ clear;
+ mes l("Repeat how many times?");
+ next;
+ menuint
+ l("Send only once"), 1,
+ l("Send 2 times"), 2,
+ l("Send 3 times"), 3,
+ l("Send 5 times"), 5,
+ l("Send 10 times"), 10,
+ l("Send 20 times"), 20,
+ l("Send indefinitely"), 0;
+
+ return @menuret;
+ }
+
+ function setOnLogin {
+ if (getarg(0,0) == 0)
+ {
+ return 1;
+ }
+ clear;
+ mes l("Send this message also on login?");
+ next;
+ select
+ l("No"),
+ l("Yes");
+
+ return (@menu - 1);
+ }
+
+ function newBroadcast {
+ do
+ {
+ setnpcdialogtitle l("Scheduled broadcasts - Create new");
+
+ // go through all steps
+ .@msg$ = setMessage();
+ .@int = setInterval();
+ .@max = setMaxRep(.@int);
+ .@login = setOnLogin(.@int);
+
+ // recap
+ clear;
+ mes l("Message:");
+ mes "---";
+ mes .@msg$;
+ mes "---";
+ if (.@int)
+ {
+ mes l("Interval: every @@ hour(s)", .@int);
+ mes l("Repeat: @@ times", .@max ? .@max : "∞");
+ mes l("Sent on login: @@", .@login ? l("yes") : l("no"));
+ }
+ else
+ {
+ mes l("Interval: (none, only sent on login)");
+ mes l("Sent on login: yes");
+ }
+
+ next;
+ select
+ menuimage("actions/cancel", l("Discard")),
+ menuimage("actions/edit", l("Start over")),
+ menuimage("actions/test", l("Start broadcasting")),
+ menuimage("actions/test", l("Start broadcasting, and make an extra broadcast right now"));
+
+ switch (@menu)
+ {
+ case 3:
+ case 4:
+ stopnpctimer "@sched";
+ $@SCHED_Opt[0] = .@login;
+ $@SCHED_Opt[1] = .@int;
+ $@SCHED_Opt[2] = 0;
+ $@SCHED_Opt[3] = .@max;
+ $@SCHED_Opt[4] = 0;
+ $@SCHED_Msg$ = .@msg$;
+ if (.@int)
+ {
+ initnpctimer "@sched";
+ }
+ if (@menu == 4)
+ {
+ announce $@SCHED_Msg$, bc_all;
+ }
+ case 1: return;
+ }
+
+ } while(1);
+ }
+
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Scheduled broadcasts");
+ mes l("This menu allows you to set the scheduled broadcast that is sent to all players at a specific interval.");
+ mes "";
+
+ .@a = $@SCHED_Msg$ != ""; // any active broadcast?
+ mes "---";
+ mes .@a ? $@SCHED_Msg$ : "(" + l("no active broadcast") +")";
+ mes "---";
+ if (.@a)
+ {
+ mes l("Sent on login: @@", ($@SCHED_Opt[0] ? l("yes") : l("no")));
+ if ($@SCHED_Opt[1])
+ {
+ .@next = max(1, ((3600000 * ($@SCHED_Opt[1] - $@SCHED_Opt[4])) - getnpctimer(0, "@sched")));
+ mes l("Interval: every @@ hour(s)", $@SCHED_Opt[1]);
+ mes l("Next broadcast: @@", FuzzyTime(time_from_ms(.@next)));
+ }
+ else
+ {
+ mes l("Interval: (none, only sent on login)");
+ mes l("Next broadcast: (never)");
+ }
+ mes l("Sent: @@ times out of @@", $@SCHED_Opt[2], ($@SCHED_Opt[3] ? $@SCHED_Opt[3] : "∞"));
+ }
+ next;
+
+ select
+ menuimage("actions/abort", l("Abort")),
+ rif(.@a, menuimage("actions/test", l("Manually trigger the current broadcast"))),
+ rif(.@a, menuimage("actions/remove", l("Stop broadcasting"))),
+ rif(!(.@a), menuimage("actions/add", l("Set a new broadcast"))),
+ rif(getarg(0,0), menuimage("actions/home", l("Return to Super Menu")));
+
+ switch (@menu)
+ {
+ case 2: announce $@SCHED_Msg$, bc_all; break;
+ case 3: $@SCHED_Msg$ = ""; break;
+ case 4: newBroadcast; break;
+ default: return;
+ }
+ } while (1);
+}
+
+
+
+- script @sched 32767,{
+ end;
+
+OnTimer3600000:
+ if ($@SCHED_Msg$ == "")
+ {
+ stopnpctimer;
+ end;
+ }
+
+ ++$@SCHED_Opt[4]; // increase hours counter
+ if ($@SCHED_Opt[4] == $@SCHED_Opt[1])
+ {
+ stopnpctimer;
+ ++$@SCHED_Opt[2]; // increase total counter
+ announce $@SCHED_Msg$, bc_all;
+ $@SCHED_Opt[4] = 0; // reset hours counter
+ if ($@SCHED_Opt[2] >= $@SCHED_Opt[3] && $@SCHED_Opt[3] > 0)
+ {
+ $@SCHED_Msg$ = ""; // reset message
+ end;
+ }
+ }
+ initnpctimer;
+ end;
+
+OnCall:
+ if (!is_evtc() && !is_dev())
+ {
+ end;
+ }
+
+ StoneBoard;
+ closedialog;
+ end;
+
+OnPCLoginEvent:
+ if ($@SCHED_Opt[0] && $@SCHED_Msg$ != "")
+ {
+ announce $@SCHED_Msg$, bc_self;
+ }
+ end;
+
+OnInit:
+ bindatcmd "sched", "@sched::OnCall", 0, 99, 0;
+}
diff --git a/npc/commands/super-menu.txt b/npc/commands/super-menu.txt
new file mode 100644
index 000000000..5e5fb6f79
--- /dev/null
+++ b/npc/commands/super-menu.txt
@@ -0,0 +1,66 @@
+function script SuperMenu {
+ do
+ {
+ if (debug && !is_dev())
+ {
+ GlobalDebugMenu;
+ return;
+ }
+
+ clear;
+ setnpcdialogtitle l("Super Menu");
+ mes l("This menu contains all options available to you, based on your access privileges.");
+ mes "";
+ mes l("What do you want to access?");
+ next;
+ select
+ l("Scheduled broadcasts"),
+ l("MOTD"),
+ rif(is_evtc(), l("Event management")),
+ l("Debug");
+
+ switch (@menu)
+ {
+ case 1: StoneBoard 1; break;
+ case 2: MOTDConfig 1; break;
+ case 3: GlobalEventMenu 1; break;
+ case 4: GlobalDebugMenu 1; break;
+ }
+ } while (1);
+}
+
+
+
+- script @super 32767,{
+ end;
+
+OnCall:
+
+ if (!debug && !is_dev())
+ {
+ dispbottom l("You do not have the required access privileges to use the Super Menu.");
+ end;
+ }
+
+ SuperMenu;
+ closedialog;
+ end;
+
+OnPCLoginEvent:
+ .@debug_skill = getskilllv(EVOL_SUPER_MENU);
+
+ if (.@debug_skill > 0 && !debug)
+ {
+ skill EVOL_SUPER_MENU, 0, 0; // remove debug skill
+ }
+
+ else if (.@debug_skill < 1 && debug)
+ {
+ skill EVOL_SUPER_MENU, 1, 0; // give debug skill
+ }
+ end;
+
+OnInit:
+ bindatcmd "super", "@super::OnCall", 0, 99, 0;
+ bindatcmd "numa", "@super::OnCall", 0, 99, 0; // alias for those used to TMW's @numa
+}
diff --git a/npc/commands/warp.txt b/npc/commands/warp.txt
new file mode 100644
index 000000000..e64b87db1
--- /dev/null
+++ b/npc/commands/warp.txt
@@ -0,0 +1,116 @@
+// @w atcommand
+// warps using anchors or map name
+//
+// group lv: 1
+// group char lv: 2
+// log: True
+//
+// usage:
+// @w <map or anchor> [, x [, y]]
+// #w "char" <map or anchor> [, x [, y]]
+//
+// example:
+// @w artis
+// #w "char" artis
+
+- script @w 32767,{
+ end;
+
+OnCall:
+ .@request$ = strtoupper(strip(.@atcmd_parameters$[0])); // sanitize
+ .@map$ = "";
+ .@x = 0;
+ .@y = 0;
+
+ for (.@i = 0; .@i < .count; .@i += 2)
+ {
+ if (.@request$ ~= .aliases$[.@i])
+ {
+ sscanf .aliases$[.@i + 1], "%s %d %d", .@map$, .@x, .@y;
+ break;
+ }
+ }
+
+ if (.@map$ == "")
+ {
+ .@map$ = .@atcmd_parameters$[0];
+ }
+
+ if (.@atcmd_parameters$[2] != "")
+ {
+ .@x = atoi(.@atcmd_parameters$[1]);
+ .@y = atoi(.@atcmd_parameters$[2]);
+ }
+
+ // FIXME: here getmapusers() is used only to check if the map exists
+ // replace this when/if we get a dedicated function for that
+ if (getmapusers(.@map$) < 0)
+ {
+ end; // invalid map
+ }
+
+ while (!checkcell(.@map$, .@x, .@y, cell_chkpass))
+ {
+ if (.@e == 50) end;
+ .@x = rand(20, 250);
+ .@y = rand(20, 250);
+ ++.@e;
+ }
+
+ cwarp .@map$, .@x, .@y; // XXX: maybe here use a slide_or_warp function
+
+OnInit:
+ setarray .aliases$[0],
+
+ // ARTIS
+ "^ART", "001-1 89 86", // artis town square
+ "^LIGHT", "001-2-0 37 32", // light armor shop
+ "^NOBLE1?$", "001-2-1 37 37", // noble house 1
+ "^NOBLE2$", "001-2-10 40 38", // noble house 2
+ "^NOBLE3$", "001-2-11 45 33", // noble house 3
+ "^NOBLE4$", "001-2-12 34 32", // noble house 4
+ "^NOBLE5$", "001-2-15 34 38", // noble house 5
+ "^MOON", "001-2-2 39 34", // moon's house
+ "^LIB", "001-2-4 49 37", // library
+ "^CITY|^HALL", "001-2-7 36 38", // city hall
+ "^HARB|^MASTER", "001-2-16 32 33", // harbourmaster
+ "^WARE", "001-2-18 39 31", // warehouse
+ "^MERCH|^BANK", "001-2-19 29 31", // merchant hall
+ "^SHIP2$", "001-2-21 30 28", // la johanne (artis)
+ "^ALCH", "001-2-26 30 32", // alchemist
+ "^BLACK|SMITH", "001-2-27 35 32", // blacksmith
+ "^RED|PLUSH|^INN", "001-2-28 32 32", // red plush inn
+ "^LEG", "001-2-33 34 36", // legion
+
+ // PROLOGUE
+ "^START|^BEGIN", "000-0 22 24", // starting point
+ "^START2$", "000-0-0 26 28", // starting point step 2
+ "^START3$", "000-0-1 26 28", // starting point step 3
+ "^DRA|ISLAND", "000-1 77 110", // drasil island
+ "^FIRST|^DECK1?$", "000-2-0 27 27", // first deck
+ "^SECOND|^DECK2$", "000-2-1 53 33", // second deck
+ "^HOLD$", "000-2-2 43 30", // hold
+ "^NARD", "000-2-3 21 27", // nard's room
+ "^ALIG|^HID", "000-2-4 36 29", // alige's hideout
+
+ // WOODLAND
+ "^HURN", "008-1 79 64", // hurnscald: town square
+ "^CELE", "008-2-0 25 27", // hurnscald: celestia
+ "^HMER", "008-2-1 33 39", // hurnscald: merchant guild
+ "^RUST", "008-2-2 37 30", // hurnscald: inn
+ "^ARRO|^ARCH", "008-2-6 27 29", // hurnscald: archery shop
+ "^A?POT", "008-2-7 34 27", // hurnscald: potion shop
+ "^HBLA", "008-2-8 36 34", // hurnscald: forge
+ "^HHAL|^HCIT", "008-2-10 36 31", // hurnscald: city hall
+ "HOSP|CLIN", "008-2-13 25 31"; // hurnscald: clinic / hospital
+
+ .count = getarraysize(.aliases$[0]);
+
+ if (debug > 0)
+ {
+ bindatcmd "w", "@w::OnCall", 0, 2, 0;
+ end;
+ }
+
+ bindatcmd "w", "@w::OnCall", 1, 2, 1;
+}
diff --git a/npc/commands/zeny.txt b/npc/commands/zeny.txt
new file mode 100644
index 000000000..77f6d2dea
--- /dev/null
+++ b/npc/commands/zeny.txt
@@ -0,0 +1,98 @@
+// @esp atcommand
+// changes the number of Esperin
+//
+// group lv: 3
+// group char lv: 99
+// log: True
+//
+// usage:
+// @esp <delta>
+// #esp "char" <delta>
+//
+// example:
+// @esp +5
+// @esp -5
+// @esp +++
+
+- script @esp 32767,{
+ end;
+
+OnCall:
+ .@delta$ = .@atcmd_parameters$[0];
+
+ if (debug && startswith(.@delta$, "--"))
+ {
+ Zeny = 0;
+ if (.@delta$ == "---")
+ {
+ BankVault = 0;
+ }
+ }
+ else if (debug && (startswith(.@delta$, "++") || .@delta$ == ""))
+ {
+ Zeny = MAX_ZENY;
+ if (.@delta$ == "+++")
+ {
+ BankVault = MAX_BANK_ZENY;
+ }
+ }
+ else
+ {
+ .@d = atoi(.@delta$);
+ if (.@d < 0)
+ {
+ .@a = Zeny + .@d; // The amount of zeny remaining after
+ if (.@a < 0) // If we can't remove that much zeny, try removing from bank too
+ {
+ Zeny = 0;
+ .@b = BankVault + .@a; // amount remaining in bank after
+ if (.@b < 0)
+ {
+ BankVault = 0;
+ }
+ else
+ {
+ BankVault += .@a;
+ }
+ }
+ else // We can remove that much zeny
+ {
+ Zeny += .@d;
+ }
+ }
+ else
+ {
+ .@a = Zeny + .@d; // The amount of zeny after
+ if (.@a < 0 || .@a >= MAX_ZENY) // If we can't add that much zeny, try adding to bank
+ {
+ .@c = .@d - (.@a - Zeny); // the amount to put in bank
+ Zeny = MAX_ZENY;
+ .@b = BankVault + .@c; // amout in bank after
+ if (.@b < 0 || .@b == MAX_BANK_ZENY)
+ {
+ BankVault = MAX_BANK_ZENY;
+ }
+ else
+ {
+ BankVault += .@c;
+ }
+ }
+ else // We can add that much zeny
+ {
+ Zeny += .@d;
+ }
+ }
+ }
+ end;
+
+OnInit:
+ if (debug > 0)
+ {
+ bindatcmd "e", "@esp::OnCall", 0, 99, 0;
+ bindatcmd "esp", "@esp::OnCall", 0, 99, 0;
+ bindatcmd "money", "@esp::OnCall", 0, 99, 0;
+ end;
+ }
+
+ bindatcmd "esp", "@esp::OnCall", 3, 99, 1;
+}
diff --git a/npc/config/hairstyle_config.txt b/npc/config/hairstyle_config.txt
new file mode 100644
index 000000000..de2d0467a
--- /dev/null
+++ b/npc/config/hairstyle_config.txt
@@ -0,0 +1,24 @@
+// Hairstyle config
+// set array of style and colors
+
+001-2-29,37,31,0 script hairstyle_config NPC_HIDDEN,0,0,{
+
+ end;
+
+OnInit:
+ setarray $@hairstyle$[0], "(none)", "Bald", "Bowl cut", "Combed back",
+ "Emo", "Mohawk", "Pompadour", "Center parting", "Long and slick",
+ "Short and curly", "Pigtails", "Long and curly", "Parted",
+ "Perky ponytail", "Wave", "Mane", "Bun", "Wavy", "Bunches",
+ "Long ponytail", "Infinitely long", "Choppy", "Wild", "Punk",
+ "Imperial", "Side strand", "Messy", "Flat ponytail",
+ "Tapered Nape";
+
+ setarray $@haircolor$[0], "Off black", "Ash brown", "Dark brown",
+ "Dark copper", "Auburn brown", "Honey brown", "Copper blonde",
+ "Golden blonde", "Pure platinum", "Cherry blossom", "Pinky pink",
+ "Fire red", "Light violet", "Purple plum", "Navy blue",
+ "Lagoon blue", "Twisted teal", "Spring Green", "Forest Green",
+ "Silver Grey", "Esperia Blue";
+ end;
+}
diff --git a/npc/dev/ci_test.txt b/npc/dev/ci_test.txt
new file mode 100644
index 000000000..6ee12452a
--- /dev/null
+++ b/npc/dev/ci_test.txt
@@ -0,0 +1,47 @@
+//================= Hercules Script =======================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2015 Hercules Dev Team
+//= Copyright (C) 2014 Haru
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Script engine self-tests, CI integration
+//================= Description ===========================================
+//= This script depends on npc/dev/test.txt, and extends it so that it can
+//= be called in a CI environment and returns an appropriate value upon
+//= termination.
+//================= Current Version =======================================
+//= 1.0
+//================= Additional Comments ===================================
+//= This script requires the script_mapquit plugin to be loaded.
+//= Usage: ./map-server --load-plugin script_mapquit --load-script npc/dev/test.txt --load-script npc/dev/ci_test.txt
+//=========================================================================
+
+- script HerculesSelfTestCI FAKE_NPC,{
+ end;
+
+OnInit:
+ .@val = callfunc("HerculesSelfTestHelper");
+ mapquit(.@val);
+ end;
+}
diff --git a/npc/dev/test.txt b/npc/dev/test.txt
new file mode 100644
index 000000000..e9058aee0
--- /dev/null
+++ b/npc/dev/test.txt
@@ -0,0 +1,814 @@
+//================= Hercules Script =======================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2013-2015 Hercules Dev Team
+//= Copyright (C) 2013-2015 Haru
+//=
+//= Hercules is free software: you can redistribute it and/or modify
+//= it under the terms of the GNU General Public License as published by
+//= the Free Software Foundation, either version 3 of the License, or
+//= (at your option) any later version.
+//=
+//= This program is distributed in the hope that it will be useful,
+//= but WITHOUT ANY WARRANTY; without even the implied warranty of
+//= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//= GNU General Public License for more details.
+//=
+//= You should have received a copy of the GNU General Public License
+//= along with this program. If not, see <http://www.gnu.org/licenses/>.
+//=========================================================================
+//= Script engine self-tests
+//================= Description ===========================================
+//= Script to test operators and possibly other elements of the script
+//= engine, useful for regression testing.
+//================= Current Version =======================================
+//= 2.0
+//=========================================================================
+
+function script F_TestReturnValue {
+ return getarg(0);
+}
+
+function script F_TestScopeVars {
+ .@x = 2;
+ return .@x+1;
+}
+
+function script F_TestNPCVars {
+ .xt = 2;
+ return .xt+1;
+}
+
+function script F_TestDeepNestedScope {
+ if (getarg(0) <= 0)
+ return getarg(1); // Stop recursion
+ if (getarg(1))
+ return callfunc("F_TestDeepNestedScope", getarg(0)-1, getarg(1)); // Recursion step
+ .@x = 1;
+ return callfunc("F_TestDeepNestedScope", getarg(0)-1, .@x); // First step
+}
+
+function script F_TestDeepNestedScopeNPC2 {
+ if (getarg(0) <= 0)
+ return getarg(1); // Stop recursion
+ if (getarg(1))
+ return callfunc("F_TestDeepNestedScopeNPC", getarg(0)-1, getarg(1)); // Recursion step
+ .xt = 1;
+ return callfunc("F_TestDeepNestedScopeNPC", getarg(0)-1, .xt); // First step
+}
+
+function script F_TestDeepNestedScopeNPC {
+ if (getarg(0) <= 0)
+ return getarg(1); // Stop recursion
+ if (getarg(1))
+ return callfunc("F_TestDeepNestedScopeNPC2", getarg(0)-1, getarg(1)); // Recursion step
+ .xt = 1;
+ return callfunc("F_TestDeepNestedScopeNPC2", getarg(0)-1, .xt); // First step
+}
+
+function script F_TestNestedScope {
+ .@x = 1;
+ .@y = callfunc("F_TestReturnValue", .@x);
+ return .@y;
+}
+
+function script F_TestNestedScopeNPC {
+ .xt = 1;
+ .yt = callfunc("F_TestReturnValue", .xt);
+ return .yt;
+}
+
+function script F_TestArrayRefs {
+ return getelementofarray(getarg(0), getarraysize(getarg(0)) - 1);
+}
+
+function script F_TestReturnArrayRef {
+ setarray getarg(0), 5, 6, 7, 8;
+ return getarraysize(getarg(0));
+}
+
+function script F_TestScopeArrays {
+ setarray .@x, 1, 2, 3, 4;
+ copyarray .@y, getarg(0), getarraysize(getarg(0));
+ return getarraysize(.@y);
+}
+
+function script F_TestNPCArrays {
+ setarray .xt, 1, 2, 3, 4;
+ copyarray .yt, getarg(0), getarraysize(getarg(0));
+ return getarraysize(.yt);
+}
+
+function script F_TestVarOfAnotherNPC {
+ return getvariableofnpc(.xt, getarg(0));
+}
+
+- script TestVarOfAnotherNPC FAKE_NPC,{
+ // Used to test getvariableofnpc()
+ end;
+}
+
+function script HerculesSelfTestHelper {
+ if (.once > 0)
+ return .errors;
+ .once = 1;
+ .errors = 0;
+
+ // Callsub (basic)
+ callsub(OnCheck, "Callsub", 1, 1);
+ callsub(OnCheck, "Callsub (getarg default values)", 1);
+
+
+ // Array subscript
+ setarray .@a, 3, 2, 1;
+ callsub(OnCheck, "Array subscript", .@a[2]);
+
+
+ // Increment and decrement operators ++, --
+ .@x = 1;
+ .@y = .@x++; // .@y = .@x; .@x = .@x + 1;
+ callsub(OnCheck, "Suffix increment ++", .@y);
+ callsub(OnCheck, "Suffix increment ++", .@x, 2);
+ .@x = 1;
+ .@y = .@x--; // .@y = .@x; .@x = .@x - 1;
+ callsub(OnCheck, "Suffix decrement --", .@y);
+ callsub(OnCheck, "Suffix decrement --", .@x, 0);
+ .@x = 0;
+ .@y = ++.@x; // .@x = .@x + 1; .@y = .@x;
+ callsub(OnCheck, "Prefix increment ++", .@y);
+ callsub(OnCheck, "Prefix increment ++", .@x);
+ .@x = 2;
+ .@y = --.@x; // .@x = .@x - 1; .@y = .@x;
+ callsub(OnCheck, "Prefix decrement --", .@y);
+ callsub(OnCheck, "Prefix decrement --", .@x);
+
+ // Order of [] and --/++
+ .@a[1] = 0;
+ .@a[1]++; // .@a[1] = .@a[1] + 1;
+ callsub(OnCheck, "Order of [] and ++", .@a[1]);
+ .@a[1] = 2;
+ .@a[1]--; // .@a[1] = .@a[1] - 1;
+ callsub(OnCheck, "Order of [] and --", .@a[1]);
+
+
+ // Unary operators -, !, ~
+ .@x = 1;
+ .@y = -.@x; // .@y = 0 - .@x;
+ callsub(OnCheck, "Unary operator -", .@y, -1);
+ .@x = 1;
+ .@y = !.@x; // if(.@x == 0) .@y = 1; else .@y = 0;
+ callsub(OnCheck, "Unary operator !", .@y, 0);
+ .@x = 0x00000001;
+ .@y = ~.@x; // One's complement of 0x00000001 is 0xfffffffe, which is -2
+ callsub(OnCheck, "Unary operator ~", .@y, -2);
+
+ // Associativity of unary operators -, !, ~
+ .@x = 1;
+ .@y = ~ ! .@x; // .@y = ~(!.@x);
+ callsub(OnCheck, "Associativity of unary ~ and !", .@y, -1);
+ .@x = 0;
+ .@y = - ! .@x; // .@y = -(!.@x);
+ callsub(OnCheck, "Associativity of unary - and !", .@y, -1);
+ .@x = 1;
+ .@y = ~ - .@x; // .@y = ~(-.@x);
+ callsub(OnCheck, "Associativity of unary ~ and -", .@y, 0);
+ .@x = 1;
+ .@y = - ~ .@x; // .@y = -(~.@x);
+ callsub(OnCheck, "Associativity of unary - and ~", .@y, 2);
+
+ // Order of unary -, !, ~ and prefix/suffix ++/--
+ .@x = 2;
+ .@y = - --.@x; // .@y = -(--.@x);
+ callsub(OnCheck, "Order of unary - and prefix --", .@y, -1);
+ callsub(OnCheck, "Order of unary - and prefix --", .@x);
+ .@x = 1;
+ .@y = - .@x--; // .@y = -(.@x--);
+ callsub(OnCheck, "Order of unary - and suffix --", .@y, -1);
+ callsub(OnCheck, "Order of unary - and suffix --", .@x, 0);
+ .@x = 0;
+ .@y = - ++.@x; // .@y = -(++.@x);
+ callsub(OnCheck, "Order of unary - and prefix ++", .@y, -1);
+ callsub(OnCheck, "Order of unary - and prefix ++", .@x);
+ .@x = 1;
+ .@y = - .@x++; // .@y = -(.@x++);
+ callsub(OnCheck, "Order of unary - and suffix ++", .@y, -1);
+ callsub(OnCheck, "Order of unary - and suffix ++", .@x, 2);
+ .@x = 1;
+ .@y = !--.@x; // .@y = !(--.@x);
+ callsub(OnCheck, "Order of unary ! and prefix --", .@y);
+ callsub(OnCheck, "Order of unary ! and prefix --", .@x, 0);
+ .@x = 1;
+ .@y = !.@x--; // .@y = !(.@x--);
+ callsub(OnCheck, "Order of unary ! and suffix --", .@y, 0);
+ callsub(OnCheck, "Order of unary ! and suffix --", .@x, 0);
+ .@x = 0;
+ .@y = !++.@x; // .@y = !(++.@x);
+ callsub(OnCheck, "Order of unary ! and prefix ++", .@y, 0);
+ callsub(OnCheck, "Order of unary ! and prefix ++", .@x);
+ .@x = 0;
+ .@y = !.@x++; // .@y = !(.@x++);
+ callsub(OnCheck, "Order of unary ! and suffix ++", .@y);
+ callsub(OnCheck, "Order of unary ! and suffix ++", .@x);
+ .@x = 2;
+ .@y = ~--.@x; // .@y = ~(--.@x);
+ callsub(OnCheck, "Order of unary ~ and prefix --", .@y, -2);
+ callsub(OnCheck, "Order of unary ~ and prefix --", .@x, 1);
+ .@x = 1;
+ .@y = ~.@x--; // .@y = ~(.@x--);
+ callsub(OnCheck, "Order of unary ~ and suffix --", .@y, -2);
+ callsub(OnCheck, "Order of unary ~ and suffix --", .@x, 0);
+ .@x = 0;
+ .@y = ~++.@x; // .@y = ~(++.@x);
+ callsub(OnCheck, "Order of unary ~ and prefix ++", .@y, -2);
+ callsub(OnCheck, "Order of unary ~ and prefix ++", .@x, 1);
+ .@x = 1;
+ .@y = ~.@x++; // .@y = ~(.@x++);
+ callsub(OnCheck, "Order of unary ~ and suffix ++", .@y, -2);
+ callsub(OnCheck, "Order of unary ~ and suffix ++", .@x, 2);
+
+ // Binary *, /, % operators
+ .@x = 2 * 3; // .@x = 6;
+ callsub(OnCheck, "Binary * operator", .@x, 6);
+ .@x = 7 / 2; // .@x = 3;
+ callsub(OnCheck, "Binary / operator", .@x, 3);
+ .@x = 7 % 2; // .@x = 1;
+ callsub(OnCheck, "Binary % operator", .@x, 1);
+
+ // Associativity of *, /, %
+ .@x = 8 * 3 / 2; // .@x = (8 * 3) / 2;
+ callsub(OnCheck, "Associativity of * and /", .@x, 12);
+
+ // Order of binary *%/ and unary !-~
+ .@x = 2 * ! 3; // .@x = 2 * (!3);
+ callsub(OnCheck, "Order of binary * and unary !", .@x, 0);
+ .@x = ~ 1 * 2; // .@x = (~1) * 2;
+ callsub(OnCheck, "Order of unary ~ and binary *", .@x, -4);
+
+
+ // Binary +, - operators
+ .@x = 1 + 3; // .@x = 4;
+ callsub(OnCheck, "Binary + operator", .@x, 4);
+ .@x = 1 - 3; // .@x = -2;
+ callsub(OnCheck, "Binary - operator", .@x, -2);
+
+ // Associativity of +,-
+ .@x = 0x7fffffff - 0x7ffffff0 + 1; // .@x = (0x7fffffff - 0x7ffffff0) + 1; (without overflow)
+ callsub(OnCheck, "Associativity of + and -", .@x, 16);
+
+ // Order of +, - and *, /, %
+ .@x = 1 + 3 * 2; // .@x = 1 + (3 * 2);
+ callsub(OnCheck, "Order of + and *", .@x, 7);
+
+
+ // << and >> operators
+ .@x = 1<<3; // .@x = 1*2*2*2;
+ callsub(OnCheck, "Left shift << operator", .@x, 8);
+ .@x = 12>>2; // .@x = 12/2/2;
+ callsub(OnCheck, "Right shift >> operator", .@x, 3);
+
+ // Associativity of << and >>
+ .@x = 0x40000000 >> 4 << 2; // .@x = (0x40000000 >> 4) << 2
+ callsub(OnCheck, "Associativity of >> and <<", .@x, 0x10000000);
+
+ // Order of <</>> and +/-
+ .@x = 4 << 2 + 1; // .@x = 4 << (2+1);
+ callsub(OnCheck, "Order of << and +", .@x, 32);
+
+
+ // <, <=, >, >= operators
+ .@x = (1 < 2); // true
+ .@y = (2 < 2); // false
+ callsub(OnCheck, "< operator", .@x);
+ callsub(OnCheck, "< operator", .@y, 0);
+ .@x = (1 <= 2); // true
+ .@y = (2 <= 2); // true
+ callsub(OnCheck, "<= operator", .@x);
+ callsub(OnCheck, "<= operator", .@y);
+ .@x = (2 > 1); // true
+ .@y = (2 > 2); // false
+ callsub(OnCheck, "> operator", .@x);
+ callsub(OnCheck, "> operator", .@y, 0);
+ .@x = (2 >= 1); // true
+ .@y = (2 >= 2); // true
+ callsub(OnCheck, ">= operator", .@x);
+ callsub(OnCheck, ">= operator", .@y);
+
+ // Associativity of <,<=,>,>=
+ .@x = 1 > 0 > 0; // (1 > 0) > 0 --> 1 > 0 --> true
+ callsub(OnCheck, "Associativity of > operators", .@x);
+
+ // Order of >>/<< and </<=/>/>=
+ .@x = 1 < 1 << 2; // .@x = 1 < (1<<2);
+ callsub(OnCheck, "Order of < and <<", .@x);
+
+
+ // ==, !=, ~=, ~! operators
+ .@x = (0 == 0); // true
+ .@y = (1 == 0); // false
+ callsub(OnCheck, "== operator", .@x);
+ callsub(OnCheck, "== operator", .@y, 0);
+ .@x = (1 != 0); // true
+ .@y = (1 != 1); // false
+ callsub(OnCheck, "!= operator", .@x);
+ callsub(OnCheck, "!= operator", .@y, 0);
+ .@x$ = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
+ "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. "
+ "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. "
+ "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
+ .@y = (.@x$ ~= "^Lorem.*, ([a-z]*).*(Duis).* ([a-z.]*)$");
+ callsub(OnCheck, "~= operator", .@y, 4);
+ callsub(OnCheck, "~= operator", $@regexmatchcount, 4);
+ if( $@regexmatchcount == 4 ) {
+ callsub(OnCheck, "~= operator", $@regexmatch$[0], .@x$);
+ callsub(OnCheck, "~= operator", $@regexmatch$[1], "quis");
+ callsub(OnCheck, "~= operator", $@regexmatch$[2], "Duis");
+ callsub(OnCheck, "~= operator", $@regexmatch$[3], "laborum.");
+ }
+ .@y = (.@x$ ~! "^Not Lorem.*, ([a-z]*).*(Duis).* ([a-z.]*)$");
+ callsub(OnCheck, "~! operator", .@y);
+
+ // Associativity of ==, !=
+ .@x = (1 == 0 == 0); // (1 == 0) == 0 --> 0 == 0 --> 1
+ .@y = (1 != 0 == 0); // (1 != 0) == 0 --> 1 == 0 --> 0
+ callsub(OnCheck, "Associativity of != and == operators", .@x);
+ callsub(OnCheck, "Associativity of != and == operators", .@y, 0);
+
+ // Order of </<=/>/>= and ==/!=
+ .@x = (1 == 2 > 1); // true
+ .@y = (1 < 2 == 1); // true
+ callsub(OnCheck, "Order of <,>,==", .@x);
+ callsub(OnCheck, "Order of <,>,==", .@y);
+
+
+ .@x$ = "string "
+ "concatenation" /* test */ " succeeded";
+ callsub(OnCheckStr, "String concatenation", .@x$, "string concatenation succeeded");
+
+
+ // Bitwise & operator
+ .@x = (7&4); // 0111 & 0100 --> 0100
+ .@y = (4&1); // 0100 & 0001 --> 0000
+ callsub(OnCheck, "Bitwise & operator", .@x, 4);
+ callsub(OnCheck, "Bitwise & operator", .@y, 0);
+
+ // Order of & and ==/!=
+ .@x = (4 == 7 & 4); // (4 == 7)&4
+ .@y = (1 & 3 != 1); // 1 & (3 != 1)
+ callsub(OnCheck, "Order of ==/!= and &", .@x, 0);
+ callsub(OnCheck, "Order of ==/!= and &", .@y);
+
+
+ // Bitwise ^ operator
+ .@x = (3^1); // 0011 ^ 0001 --> 0010
+ callsub(OnCheck, "Bitwise ^ operator", .@x, 2);
+
+ // Order of ^ and &
+ .@x = (0 & 2 ^ 2); // (0 & 2) ^ 2 --> (0000 & 0010) | 0010 --> 0000 ^ 0010 --> 0010
+ .@y = (2 ^ 2 & 0); // 2 ^ (2 & 0) --> 0010 | (0010 & 0000) --> 0010 ^ 0000 --> 0010
+ callsub(OnCheck, "Order of ^ and &", .@x, 2);
+ callsub(OnCheck, "Order of ^ and &", .@y, 2);
+
+
+ // Bitwise | operator
+ .@x = (3|4); // 0011 | 0100 --> 0111
+ .@y = (4|1); // 0100 | 0001 --> 0101
+ callsub(OnCheck, "Bitwise | operator", .@x, 7);
+ callsub(OnCheck, "Bitwise | operator", .@y, 5);
+
+ // Order of ^ and |
+ .@x = (2 ^ 2 | 2); // (2 ^ 1) | 4 --> (0010 ^ 0010) | 0010 --> 0000 | 0010 --> 0010
+ .@y = (2 | 2 ^ 2); // 4 | (1 ^ 2) --> 0010 | (0010 ^ 0010) --> 0010 | 0000 --> 0010
+ callsub(OnCheck, "Order of | and ^", .@x, 2);
+ callsub(OnCheck, "Order of | and ^", .@y, 2);
+
+
+ // Logical && operator
+ .@x = (1 && 1); // true
+ .@y = (0 && 1); // false
+ callsub(OnCheck, "Logical && operator", .@x);
+ callsub(OnCheck, "Logical && operator", .@y, 0);
+
+ // Associativity of && and short-circuit
+ .@x = 0;
+ .@y = (1 && 0 && (.@x = 1)); // should short circuit as false before evaluating the assignment
+ //FIXME callsub(OnCheck, "Short-circuit of &&", .@x, 0);
+ callsub(OnCheck, "Associativity of &&", .@y, 0);
+
+ // Order of bitwise | and logical &&
+ .@x = (1 && 0 | 4); // 1 && (0|4)
+ .@y = (4 | 0 && 1); // (4|0) && 1
+ callsub(OnCheck, "Order of && and |", .@x);
+ callsub(OnCheck, "Order of && and |", .@y);
+
+
+ // Logical || operator
+ .@x = (1 || 1); // true
+ .@y = (0 || 1); // true
+ callsub(OnCheck, "Logical || operator", .@x);
+ callsub(OnCheck, "Logical || operator", .@y);
+
+ // Associativity of || and short-circuit
+ .@x = 0;
+ .@y = (1 || 0 || (.@x = 1)); // should short circuit as true before evaluating the assignment
+ //FIXME callsub(OnCheck, "Short-circuit of ||", .@x, 0);
+ callsub(OnCheck, "Associativity of ||", .@y);
+
+ // Order of logical && and ||
+ .@x = (0 && 1 || 1); // (0 && 1) || 1
+ .@y = (1 || 1 && 0); // 1 || (1 && 0)
+ callsub(OnCheck, "Order of && and ||", .@x);
+ callsub(OnCheck, "Order of && and ||", .@y);
+
+ // Ternary conditional operator ?:
+ .@x = (1 ? 2 : 3); // 2
+ .@y = (0 ? 2 : 3); // 3
+ callsub(OnCheck, "Ternary conditional operator", .@x, 2);
+ callsub(OnCheck, "Ternary conditional operator", .@y, 3);
+
+ // Associativity of ?:
+ .@x = (1 ? 2 : 0 ? 3 : 4);
+ .@y = (1 ? 1 ? 2 : 3 : 5);
+ callsub(OnCheck, "Associativity of ?:", .@x, 2);
+ callsub(OnCheck, "Associativity of ?:", .@y, 2);
+
+ // Order of logical || and ternary ?:
+ .@x = (1 ? 0 : 0 || 1); // 1 ? 0 : (0 || 1) --> false
+ callsub(OnCheck, "Order of || and ?:", .@x, 0);
+
+
+ // Assignment operators
+ .@x = 1;
+ callsub(OnCheck, "Direct assignment operator =", .@x);
+ .@x += 7; // 1 + 7
+ callsub(OnCheck, "Assignment by sum +=", .@x, 8);
+ .@x -= 1; // 8 - 1
+ callsub(OnCheck, "Assignment by difference -=", .@x, 7);
+ .@x *= 2; // 7 * 2
+ callsub(OnCheck, "Assignment by product *=", .@x, 14);
+ .@x /= 2; // 14 / 2
+ callsub(OnCheck, "Assignment by quotient /=", .@x, 7);
+ .@x %= 4; // 7 % 4
+ callsub(OnCheck, "Assignment by remainder %=", .@x, 3);
+ .@x <<= 2; // 3 << 2
+ callsub(OnCheck, "Assignment by bitwise left shift <<=", .@x, 12);
+ .@x >>= 1; // 12 >> 1
+ callsub(OnCheck, "Assignment by bitwise right shift >>=", .@x, 6);
+ .@x &= 5; // 6 & 5 (0110 & 0101 --> 0100)
+ callsub(OnCheck, "Assignment by bitwise and &=", .@x, 4);
+ .@x ^= 5; // 4 ^ 5 (0100 ^ 0101 --> 0001)
+ callsub(OnCheck, "Assignment by bitwise xor ^=", .@x, 1);
+ .@x |= 2; // 1 | 2 (0001 | 0010 --> 0011)
+ callsub(OnCheck, "Assignment by bitwise or |=", .@x, 3);
+
+ // Associativity of assignment operators
+ .@x = 0; .@y = 0;
+ .@x = .@y = 1;
+ callsub(OnCheck, "Associativity of =", .@x);
+ callsub(OnCheck, "Associativity of =", .@y);
+ .@x = 0; .@y = 1;
+ .@x = .@y += 4;
+ callsub(OnCheck, "Associativity of = and +=", .@x, 5);
+ callsub(OnCheck, "Associativity of = and +=", .@y, 5);
+ .@x = 5; .@y = 3;
+ .@z = 8;
+ .@x *= .@y += 1;
+ callsub(OnCheck, "Associativity of *= and +=", .@x, 20);
+ callsub(OnCheck, "Associativity of *= and +=", .@y, 4);
+
+ .@x = 1; .@y = 3;
+ .@x += .@y * 10;
+ callsub(OnCheck, "Order of += and *", .@x, 31);
+ .@x = 1; .@y = 3;
+ .@x = .@y != 3 ? .@y = 2 : 4;
+ callsub(OnCheck, "Order of = and ?:", .@x, 4);
+ // FIXME callsub(OnCheck, "Short-circuit of ?:", .@y, 3);
+
+ .@x = 0;
+ if (0)
+ if (1)
+ .@x = 2;
+ else
+ .@x = 3;
+ callsub(OnCheck, "Dangling else", .@x, 0);
+
+
+ // Array operations
+ .@x[0] = 1;
+ callsub(OnCheck, "Array size (single value)", getarraysize(.@x), 1);
+ .@x[0] = 0;
+ callsub(OnCheck, "Array size (single value removal)", getarraysize(.@x), 0);
+
+ .@x[0] = 1;
+ .@x[1] = 2;
+ .@x[2] = 3;
+ .@x[5] = 4;
+ .@x[8] = 5;
+ .@x[9] = 0;
+ setarray .@y[0], 1, 2, 3, 0, 0, 4, 0, 0, 5;
+ callsub(OnCheck, "Array size (assignment)", getarraysize(.@x), 9);
+ callsub(OnCheck, "Array size (setarray)", getarraysize(.@y), 9);
+ for (.@i = 0; .@i < 10; ++.@i) {
+ callsub(OnCheck, "Array subscript and setarray [" + .@i + "]", .@x[.@i], .@y[.@i]);
+ }
+
+ cleararray .@x[1], 8, 6;
+ callsub(OnCheck, "cleararray (value) [0]", .@x[0], 1);
+ for (.@i = 1; .@i < 7; ++.@i) {
+ callsub(OnCheck, "cleararray (value) [" + .@i + "]", .@x[.@i], 8);
+ }
+ callsub(OnCheck, "cleararray (value) [7]", .@x[7], 0);
+ callsub(OnCheck, "cleararray (value) [8]", .@x[8], 5);
+ callsub(OnCheck, "cleararray (value) [9]", .@x[9], 0);
+
+ cleararray .@x, 0, getarraysize(.@x);
+ cleararray .@y, 0, getarraysize(.@y);
+ callsub(OnCheck, "cleararray and getarraysize", getarraysize(.@x), 0);
+ for (.@i = 0; .@i < 10; ++.@i) {
+ callsub(OnCheck, "cleararray (zero) [" + .@i + "]", .@x[.@i], 0);
+ }
+
+ cleararray .@x, 0, getarraysize(.@x);
+ setarray .@x[1], 1, 2, 0, 0, 0, 6, 7, 8, 0, 0, 0, 13, 14, 15, 16;
+ deletearray .@x;
+ callsub(OnCheck, "deletearray (clear) and getarraysize", getarraysize(.@x), 0);
+ for (.@i = 0; .@i < 18; ++.@i) {
+ callsub(OnCheck, "deletearray (clear) [" + .@i + "]", .@x[.@i], 0);
+ }
+
+ deletearray .@x;
+ deletearray .@y;
+ setarray .@x[1], 1, 2, 0, 0, 0, 6, 7, 8, 0, 0, 0, 0, 13, 14, 15, 16;
+ setarray .@y, 0, 1, 2, 0, 0, 0, 6, 7, 8, 0, 0, 0, 13, 14, 15, 16;
+ deletearray .@x[9], 1;
+ callsub(OnCheck, "deletearray (single) and getarraysize", getarraysize(.@x), 16);
+ for (.@i = 0; .@i < 18; ++.@i) {
+ callsub(OnCheck, "deletearray (single) [" + .@i + "]", .@x[.@i], .@y[.@i]);
+ }
+
+ deletearray .@x;
+ deletearray .@y;
+ setarray .@x[1], 1, 2, 0, 0, 0, 6, 7, 8, 0, 0, 0, 13, 14, 15, 16;
+ setarray .@y, 0, 1, 6, 7, 8, 0, 0, 0, 13, 14, 15, 16;
+ deletearray .@x[2], 4;
+ callsub(OnCheck, "deletearray (multiple) and getarraysize", getarraysize(.@x), 12);
+ for (.@i = 0; .@i < 18; ++.@i) {
+ callsub(OnCheck, "deletearray (multiple) [" + .@i + "]", .@x[.@i], .@y[.@i]);
+ }
+
+ deletearray .@x;
+ deletearray .@y;
+ setarray .@x[1], 1, 2, 0, 0, 0, 6, 7, 8, 0, 0, 0, 13, 14, 15, 16;
+ setarray .@y, 0, 1;
+ deletearray .@x[2], 1000;
+ callsub(OnCheck, "deletearray (large count) and getarraysize", getarraysize(.@x), 2);
+ for (.@i = 0; .@i < 18; ++.@i) {
+ callsub(OnCheck, "deletearray (large count) [" + .@i + "]", .@x[.@i], .@y[.@i]);
+ }
+
+ deletearray .@x;
+ deletearray .@y;
+ setarray .@x[1], 1, 2, 0, 0, 0, 6, 7, 8, 0, 0, 0, 13, 14, 15, 16;
+ setarray .@y, 0, 1;
+ deletearray .@x[2];
+ callsub(OnCheck, "deletearray (truncate) and getarraysize", getarraysize(.@x), 2);
+ for (.@i = 0; .@i < 18; ++.@i) {
+ callsub(OnCheck, "deletearray (truncate) [" + .@i + "]", .@x[.@i], .@y[.@i]);
+ }
+
+ deletearray .@x;
+ .@x[1] = 2;
+ .@x[65536] = 1;
+ callsub(OnCheck, "large array index", .@x[65536], 1);
+ callsub(OnCheck, "large array index and getarraysize", getarraysize(.@x), 65537);
+ .@x[65536] = 0;
+ callsub(OnCheck, "large array index (shrink)", .@x[65536], 0);
+ callsub(OnCheck, "large array index and getarraysize (shrink)", getarraysize(.@x), 2);
+ .@x[1] = 0;
+ callsub(OnCheck, "array shrink", .@x[1], 0);
+ callsub(OnCheck, "array shrink and getarraysize", getarraysize(.@x), 0);
+
+ // min and max
+ callsub(OnCheck, "min()", min(5, -10, 8, 3, -2, 1000), -10);
+ callsub(OnCheck, "max()", max(5, -10, 8, 3, -2, 1000), 1000);
+
+
+ // Constants
+ callsub(OnCheck, "'true' constant", true, 1);
+ callsub(OnCheck, "'false' constant", false, 0);
+ callsub(OnCheck, "'Piou' mob ID", Piou, 1002);
+ callsub(OnCheck, "'NV_BASIC' skill ID", NV_BASIC, 1);
+ callsub(OnCheck, "'Acorn' item ID", Acorn, 501);
+ callsub(OnCheck, "'Bread' item ID", Bread, 502);
+
+
+ // setd/getd
+ .@x = 1; .@x$ = ".@x";
+ callsub(OnCheck, "getd", getd(".@x"), 1);
+ callsub(OnCheck, "getd arguments", getd(.@x$), 1);
+ .@y = 0; .@y$ = ".@y";
+ setd(".@y", .@x);
+ callsub(OnCheck, "setd", .@y, 1);
+ setd(.@y$, 2);
+ callsub(OnCheck, "setd arguments", .@y, 2);
+ set getd(".@x"), getd(".@y");
+ callsub(OnCheck, "set getd", .@x, .@y);
+ .@y = 1;
+ setd(".@x", getd(".@y"));
+ callsub(OnCheck, "setd getd", .@x, .@y);
+
+ // getvariableofnpc
+ .xt = 2;
+ set getvariableofnpc(.xt, "TestVarOfAnotherNPC"), 1;
+ callsub(OnCheck, "Setting NPC variables of another NPC", getvariableofnpc(.xt, "TestVarOfAnotherNPC"), 1);
+ callsub(OnCheck, "Setting NPC variables of another NPC (local variable overwrite check)", .xt, 2);
+
+ // Callsub (advanced)
+ callsub(OnCheck, "Callsub return value", callsub(OnTestReturnValue, 1));
+ .@x = 1;
+ callsub(OnCheck, "Callsub return with scope variables", callsub(OnTestScopeVars), 3);
+ callsub(OnCheck, "Callsub (parent scope vars isolation)", .@x, 1);
+ callsub(OnCheck, "Callsub (nested scopes)", callsub(OnTestNestedScope), 1);
+ callsub(OnCheck, "Callsub (deeply nested scopes)", callsub(OnTestDeepNestedScope, 30, 0), 1);
+ .@x = 1;
+ .@y = callsub(OnSetReference, .@x);
+ callsub(OnCheck, "Callsub (setting references)", .@y, 2);
+ callsub(OnCheck, "Callsub (setting references)", .@x, 2);
+ deletearray .@x;
+ setarray .@x, 1, 2, 3, 4;
+ callsub(OnCheck, "Callsub (array references)", callsub(OnTestArrayRefs, .@x), 4);
+ deletearray .@x;
+ .@y = callsub(OnTestReturnArrayRef, .@x);
+ callsub(OnCheck, "Callsub return array references (size check)", getarraysize(.@x), .@y);
+ callsub(OnCheck, "Callsub return array references", getelementofarray(.@x, 3), 8);
+ deletearray .@x;
+ deletearray .@y;
+ setarray .@x, 1, 2;
+ .@z = getarraysize(.@x);
+ setarray .@y, 5, 6, 7, 8, 9;
+ callsub(OnCheck, "Callsub (copyarray from reference with the same name)", getarraysize(.@y), callsub(OnTestScopeArrays, .@y));
+ callsub(OnCheck, "Callsub (parent array vars isolation)", getarraysize(.@x), .@z);
+ deletearray .@x;
+ deletearray .@y;
+ .xt = 2;
+ set getvariableofnpc(.xt, "TestVarOfAnotherNPC"), 1;
+ callsub(OnCheck, "Callsub (return NPC variables from another NPC)", callsub(OnTestVarOfAnotherNPC, "TestVarOfAnotherNPC"), 1);
+ callsub(OnCheck, "Callsub (return NPC variables from another NPC - local variable overwrite check)", .xt, 2);
+
+ // Callfunc
+ callsub(OnCheck, "Callfunc return value", callfunc("F_TestReturnValue", 1));
+ .@x = 1;
+ callsub(OnCheck, "Callfunc return with scope variables", callfunc("F_TestScopeVars"), 3);
+ callsub(OnCheck, "Callfunc (parent scope vars isolation)", .@x, 1);
+ callsub(OnCheck, "Callfunc (nested scopes)", callfunc("F_TestNestedScope"), 1);
+ callsub(OnCheck, "Callfunc (deeply nested scopes)", callfunc("F_TestDeepNestedScope", 30, 0), 1);
+ deletearray .@x;
+ setarray .@x, 1, 2, 3, 4;
+ callsub(OnCheck, "Callfunc (array references)", callfunc("F_TestArrayRefs", .@x), 4);
+ deletearray .@x;
+ .@y = callfunc("F_TestReturnArrayRef", .@x);
+ callsub(OnCheck, "Callfunc return array references (size check)", getarraysize(.@x), .@y);
+ callsub(OnCheck, "Callfunc return array references", getelementofarray(.@x, 3), 8);
+ deletearray .@x;
+ deletearray .@y;
+ setarray .@x, 1, 2;
+ .@z = getarraysize(.@x);
+ setarray .@y, 5, 6, 7, 8, 9;
+ callsub(OnCheck, "Callfunc (copyarray from reference with the same name)", getarraysize(.@y), callfunc("F_TestScopeArrays", .@y));
+ callsub(OnCheck, "Callfunc (parent array vars isolation)", getarraysize(.@x), .@z);
+ deletearray .@x;
+ deletearray .@y;
+ .xt = 1;
+ callsub(OnCheck, "Callfunc return with NPC variables", callfunc("F_TestNPCVars"), 3);
+ callsub(OnCheck, "Callfunc (parent NPC vars isolation)", .xt, 1);
+ callsub(OnCheck, "Callfunc (nested scopes and NPC variables)", callfunc("F_TestNestedScopeNPC"), 1);
+ callsub(OnCheck, "Callfunc (deeply nested scopes and NPC variables)", callfunc("F_TestDeepNestedScopeNPC", 30, 0), 1);
+ deletearray .xt;
+ setarray .xt, 1, 2, 3, 4;
+ callsub(OnCheck, "Callfunc (array references and NPC variables)", callfunc("F_TestArrayRefs", .xt), 4);
+ deletearray .xt;
+ .yt = callfunc("F_TestReturnArrayRef", .xt);
+ callsub(OnCheck, "Callfunc return array references with NPC variables (size check)", getarraysize(.xt), .yt);
+ callsub(OnCheck, "Callfunc return array references wuth NPC variables", getelementofarray(.xt, 3), 8);
+ deletearray .xt;
+ deletearray .yt;
+ setarray .xt, 1, 2;
+ .@z = getarraysize(.@x);
+ setarray .yt, 5, 6, 7, 8, 9;
+ callsub(OnCheck, "Callfunc (copyarray from NPC variable reference with the same name)", getarraysize(.@y), callfunc("F_TestNPCArrays", .@y));
+ callsub(OnCheck, "Callfunc (parent array NPC vars isolation)", getarraysize(.@x), .@z);
+ deletearray .xt;
+ deletearray .yt;
+ .xt = 2;
+ set getvariableofnpc(.xt, "TestVarOfAnotherNPC"), 1;
+ callsub(OnCheck, "Callfunc (return NPC variables from another NPC)", callfunc("F_TestVarOfAnotherNPC", "TestVarOfAnotherNPC"), 1);
+ callsub(OnCheck, "Callfunc (return NPC variables from another NPC - local variable overwrite check)", .xt, 2);
+
+ callsub(OnCheckStr, "sprintf (%%)", sprintf("'%%'"), "'%'");
+ callsub(OnCheckStr, "sprintf (%d)", sprintf("'%d'", 5), "'5'");
+ callsub(OnCheckStr, "sprintf (neg. %d)", sprintf("'%d'", -5), "'-5'");
+ callsub(OnCheckStr, "sprintf (%u)", sprintf("'%u'", 5), "'5'");
+ callsub(OnCheckStr, "sprintf (%x)", sprintf("'%x'", 10), "'a'");
+ callsub(OnCheckStr, "sprintf (%X)", sprintf("'%X'", 31), "'1F'");
+ callsub(OnCheckStr, "sprintf (%s)", sprintf("'%s'", "Hello World!"), "'Hello World!'");
+ callsub(OnCheckStr, "sprintf (%c)", sprintf("'%c'", "Hello World!"), "'H'");
+ callsub(OnCheckStr, "sprintf (%+d)", sprintf("'%+d'", 5), "'+5'");
+ callsub(OnCheckStr, "sprintf (%{n}d)", sprintf("'%5d'", 5), "' 5'");
+ callsub(OnCheckStr, "sprintf (%-{n}d)", sprintf("'%-5d'", 5), "'5 '");
+ callsub(OnCheckStr, "sprintf (%-+{n}d)", sprintf("'%-+5d'", 5), "'+5 '");
+ callsub(OnCheckStr, "sprintf (%+0{n}d)", sprintf("'%+05d'", 5), "'+0005'");
+ callsub(OnCheckStr, "sprintf (%0*d)", sprintf("'%0*d'", 5, 10), "'00010'");
+ callsub(OnCheckStr, "sprintf (Two args)", sprintf("'%+05d' '%x'", 5, 0x7f), "'+0005' '7f'");
+ callsub(OnCheckStr, "sprintf (positional)", sprintf("'%2$+05d'", 5, 6), "'+0006'");
+ callsub(OnCheckStr, "sprintf (positional)", sprintf("'%2$s' '%1$c'", "First", "Second"), "'Second' 'F'");
+
+ if (.errors) {
+ debugmes "Script engine self-test [ \033[0;31mFAILED\033[0m ]";
+ debugmes "**** The test was completed with " + .errors + " errors. ****";
+ } else {
+ debugmes "Script engine self-test [ \033[0;32mPASSED\033[0m ]";
+ }
+ return .errors;
+ end;
+
+OnTestReturnValue:
+ return getarg(0);
+
+OnTestScopeVars:
+ .@x = 2;
+ return .@x+1;
+
+OnTestDeepNestedScope:
+ if (getarg(0) <= 0)
+ return getarg(1); // Stop recursion
+ if (getarg(1))
+ return callsub(OnTestDeepNestedScope, getarg(0)-1, getarg(1)); // Recursion step
+ .@x = 1;
+ return callsub(OnTestDeepNestedScope, getarg(0)-1, .@x); // First step
+
+OnTestNestedScope:
+ .@x = 1;
+ .@y = callsub(OnTestReturnValue, .@x);
+ return .@y;
+
+OnTestArrayRefs:
+ return getelementofarray(getarg(0), getarraysize(getarg(0)) - 1);
+
+OnTestReturnArrayRef:
+ setarray getarg(0), 5, 6, 7, 8;
+ return getarraysize(getarg(0));
+
+OnTestScopeArrays:
+ setarray .@x, 1, 2, 3, 4;
+ copyarray .@y, getarg(0), getarraysize(getarg(0));
+ return getarraysize(.@y);
+
+OnTestVarOfAnotherNPC:
+ return getvariableofnpc(.xt, getarg(0));
+
+OnReportError:
+ .@msg$ = getarg(0,"Unknown Error");
+ .@val$ = getarg(1,"");
+ .@ref$ = getarg(2,"");
+ if (.errors == 1)
+ debugmes "**** WARNING: Any self-test results past this point are unreliable because of previous errors. ****";
+ debugmes "Error: "+.@msg$+": '"+.@val$+"' (found) != '"+.@ref$+"' (expected)";
+ ++.errors;
+ //end;
+ return;
+
+OnCheck:
+ .@msg$ = getarg(0,"Unknown Error");
+ .@val = getarg(1,0);
+ .@ref = getarg(2,1);
+ if (.@val != .@ref) {
+ callsub(OnReportError, .@msg$, ""+.@val, ""+.@ref); // String coercion
+ }
+ return;
+OnCheckStr:
+ .@msg$ = getarg(0,"Unknown Error");
+ .@val$ = getarg(1,"");
+ .@ref$ = getarg(2,"");
+ if (.@val$ != .@ref$) {
+ callsub(OnReportError, .@msg$, .@val$, .@ref$);
+ }
+ return;
+OnSetReference:
+ set getarg(0), getarg(0) + 1;
+ return getarg(0);
+}
+
+- script HerculesSelfTest FAKE_NPC,{
+ end;
+
+OnInit:
+ callfunc("HerculesSelfTestHelper");
+ end;
+}
diff --git a/npc/functions/RNGesus.txt b/npc/functions/RNGesus.txt
new file mode 100644
index 000000000..f71c2f28a
--- /dev/null
+++ b/npc/functions/RNGesus.txt
@@ -0,0 +1,23 @@
+// Evol functions.
+// Authors:
+// gumi
+// Description:
+// Randomization helper functions.
+
+
+
+// any(<arg>{, ...<arg>})
+// returns one argument randomly
+
+function script any {
+ return getarg(rand(getargcount()));
+}
+
+
+
+// any_of(<array>)
+// returns any member of the array
+
+function script any_of {
+ return getelementofarray(getarg(0), getarrayindex(getarg(0)) + rand(getarraysize(getarg(0)) - getarrayindex(getarg(0))));
+}
diff --git a/npc/functions/array.txt b/npc/functions/array.txt
new file mode 100644
index 000000000..d9d649921
--- /dev/null
+++ b/npc/functions/array.txt
@@ -0,0 +1,410 @@
+// array_pad(<array>, <size>, <value>)
+// prepend or append <value> until the array is of <size> size
+// returns the amount added on success, or false (0) if nothing changed
+
+function script array_pad {
+ .@index = getarrayindex(getarg(0)); // passed index
+ .@count = getarraysize(getarg(0)) - .@index; // actual size
+ .@size = getarg(1); // desired size
+ .@absolute = (.@size >= 0 ? .@size : -(.@size)); // |size|
+ .@delta = .@absolute - .@count; // amount to fill
+
+ if (.@absolute <= .@count) {
+ return false; // nothing to do
+ }
+
+ if (.@size < 0) {
+ copyarray(getelementofarray(getarg(0), .@index + .@delta), getarg(0), .@count); // shift to the right
+ cleararray(getarg(0), getarg(2), .@delta); // prepend
+ } else {
+ cleararray(getelementofarray(getarg(0), .@index + .@count), getarg(2), .@delta); // append
+ }
+
+ return .@delta;
+}
+
+
+
+// array_replace(<array>, <needle>, <replace>{, <neq>})
+// replace every occurence of <needle> with <replace>
+// returns the number of replaced elements
+
+function script array_replace {
+ .@size = getarraysize(getarg(0));
+ .@neq = getarg(3, false);
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) ||
+ (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) {
+ set(getelementofarray(getarg(0), .@i), getarg(2));
+ ++.@count;
+ }
+ }
+
+ freeloop(false);
+ return .@count;
+}
+
+
+
+// array_find(<array>, <needle>{, <neq>})
+// return the index of the first occurence of <needle> in <array>
+// if not found it returns -1
+
+function script array_find {
+ .@size = getarraysize(getarg(0));
+ .@neq = getarg(2, false);
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) ||
+ (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) {
+ freeloop(false);
+ return .@i;
+ }
+ }
+
+ freeloop(false);
+ return -1;
+}
+
+
+
+// array_rfind(<array>, <needle>{, <neq>})
+// return the index of the last occurence of <needle> in <array>
+// if not found it returns -1
+
+function script array_rfind {
+ .@min = getarrayindex(getarg(0));
+ .@neq = getarg(2, false);
+ freeloop(true);
+
+ for (.@i = (getarraysize(getarg(0)) - 1); .@i >= .@min; --.@i) {
+ if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) ||
+ (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) {
+ freeloop(false);
+ return .@i;
+ }
+ }
+
+ freeloop(false);
+ return -1;
+}
+
+
+
+// array_exists(<array>, <needle>{, <neq>})
+// return true or false accordingly if <needle> is found in <array>
+
+function script array_exists {
+ return array_find(getarg(0), getarg(1), getarg(2, false)) > -1;
+}
+
+
+
+// array_count(<array>, <needle>{, <neq>})
+// counts the number of occurrence of <needle> in the <array>
+
+function script array_count {
+ .@size = getarraysize(getarg(0));
+ .@neq = getarg(2, false);
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) ||
+ (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) {
+ ++.@count;
+ }
+ }
+
+ freeloop(false);
+ return .@count;
+}
+
+
+
+// array_entries(<array>)
+// returns the number of non-empty entries
+
+function script array_entries {
+ if (isstr(getarg(0)) == 1) {
+ return array_count(getarg(0), "", true);
+ }
+ return array_count(getarg(0), 0, true);
+}
+
+
+
+// array_remove(<array>, <needle>{, <neq>})
+// removes every occurrence of <needle> in the <array> while shifting left
+
+function script array_remove {
+ .@size = getarraysize(getarg(0));
+ .@neq = getarg(2, false);
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) ||
+ (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) {
+ deletearray(getelementofarray(getarg(0), .@i), 1); // shift left
+ ++.@count; // increase the counter
+ --.@size; // reduce the size
+ --.@i; // step back
+ }
+ }
+
+ freeloop(false);
+ return .@count;
+}
+
+
+
+// array_reverse(<array>)
+// reverses the array
+
+function script array_reverse {
+ .@index = getarrayindex(getarg(0));
+ .@size = getarraysize(getarg(0));
+ freeloop(true);
+
+ for (.@i = .@index; .@i < ((.@size + .@index) / 2); ++.@i) {
+ swap(getelementofarray(getarg(0), .@i), getelementofarray(getarg(0), .@size + .@index - 1 - .@i)); // a <> b
+ }
+
+ freeloop(false);
+ return true;
+}
+
+
+
+// array_sum(<array>)
+// return the sum of every element of the array
+
+function script array_sum {
+ .@size = getarraysize(getarg(0));
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ .@sum += getelementofarray(getarg(0), .@i);
+ }
+
+ freeloop(false);
+ return .@sum;
+}
+
+
+
+// array_difference(<array>)
+// return the difference of every element of the array
+
+function script array_difference {
+ .@size = getarraysize(getarg(0));
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ .@diff -= getelementofarray(getarg(0), .@i);
+ }
+
+ freeloop(false);
+ return .@diff;
+}
+
+
+
+// array_product(<array>)
+// return the product of every element of the array
+
+function script array_product {
+ .@size = getarraysize(getarg(0));
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ .@prod *= getelementofarray(getarg(0), .@i);
+ }
+
+ freeloop(false);
+ return .@prod;
+}
+
+
+
+// array_quotient(<array>)
+// return the product of every element of the array
+
+function script array_quotient {
+ .@size = getarraysize(getarg(0));
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ .@quot /= getelementofarray(getarg(0), .@i);
+ }
+
+ freeloop(false);
+ return .@quot;
+}
+
+
+
+// array_shift(<array>)
+// returns the first element of the array and removes it, while shifting left
+
+function script array_shift {
+ if (isstr(getarg(0)) == 1) {
+ .@val$ = getarg(0);
+ } else {
+ .@int = true;
+ .@val = getarg(0);
+ }
+
+ deletearray(getarg(0), 1); // shift left
+
+ return .@int ? .@val : .@val$;
+}
+
+
+
+// array_unshift(<array>, <value>)
+// adds <value> to the start of the array, while shifting right
+// returns the new size
+
+function script array_unshift {
+ .@size = getarraysize(getarg(0)) + 1;
+ array_pad(getarg(0), -(.@size - getarrayindex(getarg(0))), getarg(1));
+ return .@size;
+}
+
+
+
+// array_pop(<array>)
+// returns the last element of the array and removes it
+
+function script array_pop {
+ .@last = getarraysize(getarg(0)) - 1;
+
+ if (isstr(getelementofarray(getarg(0), .@last)) == 1) {
+ .@val$ = getelementofarray(getarg(0), .@last);
+ } else {
+ .@int = true;
+ .@val = getelementofarray(getarg(0), .@last);
+ }
+
+ deletearray(getelementofarray(getarg(0), .@last), 1);
+
+ return .@int ? .@val : .@val$;
+}
+
+
+
+// array_push(<array>, <value>)
+// adds <value> to the end of the array
+// returns the new size
+
+function script array_push {
+ .@size = getarraysize(getarg(0));
+ set(getelementofarray(getarg(0), .@size), getarg(1));
+ return .@size + 1;
+}
+
+
+
+// array_shuffle(<array>)
+// shuffles the array
+
+function script array_shuffle {
+ .@index = getarrayindex(getarg(0));
+ .@size = getarraysize(getarg(0)) - .@index;
+ freeloop(true);
+
+ if (isstr(getarg(0)) == 1) {
+ copyarray(.@tmp$[0], getarg(0), .@size);
+ for (; .@size >= 1; --.@size) {
+ set(getelementofarray(getarg(0), .@index + .@size - 1), array_shift(.@tmp$[rand(.@size)]));
+ }
+ } else {
+ copyarray(.@tmp[0], getarg(0), .@size);
+ for (; .@size >= 1; --.@size) {
+ set(getelementofarray(getarg(0), .@index + .@size - 1), array_shift(.@tmp[rand(.@size)]));
+ }
+ }
+
+ freeloop(false);
+ return true;
+}
+
+
+
+// array_unique(<array>{, <threshold>})
+// allows entries to appear up to <threshold> in the array
+
+function script array_unique {
+ .@size = getarraysize(getarg(0));
+ .@max = getarg(1, 1);
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ .@count = 1;
+ for (.@e = .@i + 1; .@e < .@size; ++.@e) {
+ if (getelementofarray(getarg(0), .@i) == getelementofarray(getarg(0), .@e)) {
+ if (++.@count >= .@max) {
+ deletearray(getelementofarray(getarg(0), .@e), 1);
+ ++.@removed; // increase counter
+ --.@size; // reduce size
+ --.@e; // step back
+ }
+ }
+ }
+ }
+
+ freeloop(false);
+ return .@removed;
+}
+
+
+
+// array_diff(<array1>, <array2>{, <array>...}, <array>)
+// compares array1 against one or more other arrays and fills the last array
+// with the values in array1 that are not present in any of the other arrays
+// returns the number of entries not matching
+
+function script array_diff {
+ .@size = getarraysize(getarg(0));
+ .@index = getarrayindex(getarg(0));
+ freeloop(true);
+
+ for (.@a = 1; .@a < (getargcount() - 1); ++.@a) {
+ for (.@i = .@index; .@i < .@size; ++.@i) {
+ if (!array_exists(getarg(.@a), getelementofarray(getarg(0), .@i))) {
+ array_push(getarg(getargcount() - 1), getelementofarray(getarg(0), .@i));
+ ++.@count;
+ }
+ }
+ }
+
+ freeloop(false);
+ return .@count;
+}
+
+
+
+// array_filter(<array>, "<function>")
+// filters the array using a callback function
+
+function script array_filter {
+ .@size = getarraysize(getarg(0));
+ .@neq = getarg(2, false);
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ .@eq = callfunc(getarg(1), getelementofarray(getarg(0), .@i)) != false;
+ if ((.@neq && .@eq) || (!(.@neq) && !(.@eq))) {
+ deletearray(getelementofarray(getarg(0), .@i), 1); // shift left
+ ++.@count; // increase the counter
+ --.@size; // reduce the size
+ --.@i; // step back
+ }
+ }
+
+ freeloop(false);
+ return .@count;
+}
diff --git a/npc/functions/asklanguage.txt b/npc/functions/asklanguage.txt
new file mode 100644
index 000000000..4bea4bd11
--- /dev/null
+++ b/npc/functions/asklanguage.txt
@@ -0,0 +1,80 @@
+// Evol functions.
+// Author:
+// Reid
+// Description:
+// Function setting the player language
+
+function script asklanguage {
+
+ .@nb_language = 11;
+
+ switch (getarg(0, 0))
+ {
+ case LANG_ON_SEA:
+ setarray .@messages$[0], "I hear you... (English)", // English
+ "Je vous entends... (Français)", // French
+ "Да я вас слышу... (Русский)", // Russian
+ "Te oigo... (Español)", // Spanish
+ "Eu te ouço... (Português)", // Portuguese
+ "Ich höre euch... (Deutsch)", // German
+ "'k hoar ui wel... (Vlaams)", // Flemish
+ "Słyszę cię... (Polski)", // Polish
+ "Vi sento... (Italiano)", // Italian
+ "Ik kan je horen... (Nederlands)", // Dutch
+ "Et escolto (Català)", // Catalan
+ "Mi aŭdas vin... (Angle)"; // Esperanto
+ break;
+ case LANG_IN_SHIP:
+ setarray .@messages$[0], "I speak English.", // English
+ "Je parle français.", // French
+ "Я говорю на русском.", // Russian
+ "Hablo Español.", // Spanish
+ "Eu falo Português.", // Portuguese
+ "Ich spreche Deutsch.", // German
+ "'k klappe Vloams", // Flemish
+ "Mówię po polsku.", // Polish
+ "Parlo Italiano.", // Italian
+ "Ik spreek Nederlands.", // Dutch
+ "Parlo català.", // Catalan
+ "Mi parolas Esperanton."; // Esperanto
+ break;
+ default:
+ return;
+ }
+
+ setarray .@flags$[0], "flags/en",
+ "flags/fr",
+ "flags/ru",
+ "flags/es",
+ "flags/pt_BR",
+ "flags/de",
+ "flags/vls",
+ "flags/pl",
+ "flags/it",
+ "flags/nl_BE",
+ "flags/ca",
+ "flags/eo";
+
+ .@menustr$ = "";
+ .@separator$ = ":";
+
+ for (.@i = 0; .@i <= .@nb_language; .@i++)
+ {
+ if (.@i == .@nb_language)
+ {
+ .@separator$ = "";
+ }
+ .@menustr$ = .@menustr$ + .@flags$[.@i] + "|" + .@messages$[.@i] + .@separator$;
+ }
+
+ select(.@menustr$);
+
+ .@lang = @menu - 1;
+
+ if (.@lang >= 0 || .@lang <= .@nb_language)
+ {
+ Lang = .@lang;
+ }
+
+ return;
+}
diff --git a/npc/functions/asleep.txt b/npc/functions/asleep.txt
new file mode 100644
index 000000000..aa5abd635
--- /dev/null
+++ b/npc/functions/asleep.txt
@@ -0,0 +1,19 @@
+// Evol functions.
+// Authors:
+// Alige
+// Reid
+// Description:
+// Tell a random sleeping sound.
+// Variables:
+// .@rand = Random number between the number of "sleeping" choice.
+
+function script asleep {
+ switch(rand(5)) {
+ case 0: npctalkonce(l("Zzzzzzzzz...")); break;
+ case 1: npctalkonce(l("Rrrr... Pchhhh...")); break;
+ case 2: npctalkonce(l("Ggrmm... Grmmmm...")); break;
+ case 3: npctalkonce(l("Hm... Shhhh...")); break;
+ default: emotion(E_SLEEPY);
+ }
+ end;
+}
diff --git a/npc/functions/bank.txt b/npc/functions/bank.txt
new file mode 100644
index 000000000..5b2813797
--- /dev/null
+++ b/npc/functions/bank.txt
@@ -0,0 +1,134 @@
+// Evol scripts.
+// Authors:
+// gumi
+// Reid
+
+function script MerchantGuild_Bank {
+ do
+ {
+ if (BankVault > 0)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You currently have @@ Esperin on your bank account.",
+ format_number(BankVault)),
+ l("What do you want to do with your money?");
+ }
+ else
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("What do you want to do with your money?");
+ }
+
+ select
+ rif(Zeny > 0, l("Deposit.")),
+ rif(BankVault > 0, l("Withdraw.")),
+ l("I'm done.");
+
+ switch (@menu)
+ {
+ case 1:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("How much do you want to deposit?");
+
+ menuint
+ l("Other."), -1,
+ rif(Zeny >= 5000, format_number(5000) + " E."), 5000,
+ rif(Zeny >= 10000, format_number(10000) + " E."), 10000,
+ rif(Zeny >= 25000, format_number(25000) + " E."), 25000,
+ rif(Zeny >= 50000, format_number(50000) + " E."), 50000,
+ rif(Zeny >= 100000, format_number(100000) + " E."), 100000,
+ rif(Zeny >= 250000, format_number(250000) + " E."), 250000,
+ rif(Zeny >= 500000, format_number(500000) + " E."), 500000,
+ rif(Zeny >= 1000000, format_number(1000000) + " E."), 1000000,
+ l("All of my money."), -2,
+ l("I changed my mind."), -3;
+
+ switch (@menuret)
+ {
+ case -1:
+ input @menuret;
+ break;
+ case -2:
+ @menuret = Zeny;
+ }
+
+ if (@menuret > 0)
+ {
+ if (@menuret > Zeny)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You do not have enough Esperin on yourself.");
+ break;
+ }
+
+ @menuret = min(MAX_BANK_ZENY, @menuret); // make sure the variable can't overflow
+ .@before = BankVault; // amount before the deposit
+ .@max = MAX_BANK_ZENY - BankVault; // maximum possible deposit
+ .@deposit = min(.@max, @menuret); // actual deposit
+
+ if (.@deposit > 0)
+ {
+ BankVault += .@deposit; // add to bank
+ Zeny -= .@deposit; // remove from inventory
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You made a cash deposit of @@ E.", format_number(.@deposit));
+ }
+ }
+ break;
+
+ case 2:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("How much do you want to withdraw?");
+
+ menuint
+ l("Other."), -1,
+ rif(BankVault >= 5000, format_number(5000) + " E."), 5000,
+ rif(BankVault >= 10000, format_number(10000) + " E."), 10000,
+ rif(BankVault >= 25000, format_number(25000) + " E."), 25000,
+ rif(BankVault >= 50000, format_number(50000) + " E."), 50000,
+ rif(BankVault >= 100000, format_number(100000) + " E."), 100000,
+ rif(BankVault >= 250000, format_number(250000) + " E."), 250000,
+ rif(BankVault >= 500000, format_number(500000) + " E."), 500000,
+ rif(BankVault >= 1000000, format_number(1000000) + " E."), 1000000,
+ l("All of my money."), -2,
+ l("I changed my mind."), -3;
+
+ switch (@menuret)
+ {
+ case -1:
+ input @menuret;
+ break;
+ case -2:
+ @menuret = BankVault;
+ }
+
+ if (@menuret > 0)
+ {
+ if (@menuret > BankVault)
+ {
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You do not have enough Esperin on your bank account.");
+ break;
+ }
+
+ @menuret = min(MAX_ZENY, @menuret); // make sure the variable can't overflow
+ .@before = Zeny; // amount before the withdrawal
+ .@max = MAX_ZENY - Zeny; // maximum possible withdrawal
+ .@withdrawal = min(.@max, @menuret); // actual withdrawal
+
+ if (.@withdrawal > 0)
+ {
+ Zeny += .@withdrawal; // add to inventory
+ BankVault -= .@withdrawal; // remove from bank
+
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("You withdrew a total of @@ E.", format_number(.@withdrawal));
+ }
+ }
+ break;
+
+ default: return;
+ }
+ } while (true);
+}
diff --git a/npc/functions/barber.txt b/npc/functions/barber.txt
new file mode 100644
index 000000000..370285b76
--- /dev/null
+++ b/npc/functions/barber.txt
@@ -0,0 +1,110 @@
+// Evol scripts.
+// Authors:
+// omatt
+// Reid
+// Travolta
+// Description:
+// Function for supporting barber NPC.
+
+function script BarberSayStyle {
+
+ .@get_color = getlook(LOOK_HAIR_COLOR);
+ .@get_look = getlook(LOOK_HAIR);
+ .@style_name$ = $@hairstyle$[.@get_look];
+ .@color_name$ = $@haircolor$[.@get_color];
+
+ switch (getarg(0))
+ {
+ case 1:
+ message strcharinfo(0), l("@@", .@style_name$);
+ break;
+ case 2:
+ message strcharinfo(0), l("@@", .@color_name$);
+ break;
+ case 3:
+ speech S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("Your hairstyle is @@ and its color is @@.", .@style_name$, .@color_name$);
+ break;
+ }
+ return;
+}
+function script BarberChangeStyle {
+ do
+ {
+ .@hairsizearray = getarraysize($@hairstyle$);
+ .@get_look = getlook(LOOK_HAIR);
+
+ // Here .@i starts from 1 because hairstyle 0 doesn't exist.
+ for (.@i = 1; .@i < .@hairsizearray; .@i++)
+ {
+ .@menustr$ = .@menustr$
+ + rif(.@get_look != .@i, l("" + $@hairstyle$[.@i] + ""))
+ + ":";
+ }
+
+ .@menustr$ = .@menustr$ + l("I'm fine for now, thank you.");
+
+ .@idx = select(l("As you want!"),.@menustr$);
+
+ if (.@idx == .@i + 1) return; // last choice to quit dialog
+
+ switch (@menu)
+ {
+ case 1:
+ do
+ {
+ // here "- 1" because i don't use the 0 of array
+ .@rand_hair = rand(1,(.@hairsizearray - 1));
+ } while (.@rand_hair == getlook(LOOK_HAIR));
+ setlook LOOK_HAIR, .@rand_hair;
+ setlook LOOK_HAIR_COLOR, getlook(LOOK_HAIR_COLOR);
+ BarberSayStyle 1;
+ break;
+ default:
+ // and here "- 1" because the first choice is taken by the random
+ setlook LOOK_HAIR, (@menu - 1);
+ setlook LOOK_HAIR_COLOR, getlook(LOOK_HAIR_COLOR);
+ break;
+ }
+ .@menustr$ = "";
+ } while (1);
+}
+
+function script BarberChangeColor {
+ do
+ {
+ .@get_look = getlook(LOOK_HAIR_COLOR);
+ .@hairsizearray = getarraysize($@haircolor$);
+
+ for (.@i = 0; .@i < .@hairsizearray; .@i++)
+ {
+ .@menustr$ = .@menustr$
+ + rif(.@get_look != .@i, l("" + $@haircolor$[.@i] + ""))
+ + ":";
+ }
+
+ .@menustr$ = l("Surprise me!") + ":" + .@menustr$ + l("I'm fine for now, thank you.");
+
+ .@idx = select(.@menustr$);
+
+ if (.@idx == .@i + 2) return;
+
+ switch (@menu)
+ {
+ case 1:
+ do
+ {
+ .@rand_color = rand(0, .@hairsizearray);
+ } while (.@rand_color == getlook(LOOK_HAIR_COLOR));
+ setlook LOOK_HAIR_COLOR, .@rand_color;
+ BarberSayStyle 2;
+ break;
+ default:
+ setlook LOOK_HAIR_COLOR, (@menu - 2);
+ break;
+ }
+ .@menustr$ = "";
+ } while (1);
+
+ return;
+}
diff --git a/npc/functions/beds.txt b/npc/functions/beds.txt
new file mode 100644
index 000000000..4ab8b6a77
--- /dev/null
+++ b/npc/functions/beds.txt
@@ -0,0 +1,30 @@
+// Evol functions.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Beds utility functions
+
+function script bedTouch {
+ if (PC_IS_DEAD)
+ {
+ PC_IS_DEAD = 0;
+ if (INN_REGISTER == REDPLUSH_INN)
+ {
+ INN_REGISTER = NO_INN;
+ percentheal 100,100;
+ }
+ }
+ close;
+}
+
+function script bedClic {
+ narrator S_LAST_NEXT, l("Do you want to use this place as save point?");
+
+ if (askyesno() == ASK_YES)
+ {
+ savepointparticle getarg(0, ""), getarg(1, -1), getarg(2, -1), getarg(3, NO_INN);
+ }
+ closedialog;
+ close;
+}
diff --git a/npc/functions/clientversion.txt b/npc/functions/clientversion.txt
new file mode 100644
index 000000000..9d502be3d
--- /dev/null
+++ b/npc/functions/clientversion.txt
@@ -0,0 +1,20 @@
+// Evol functions.
+// Author:
+// 4144
+// Description:
+// Function checking the client version and reports if it is too old.
+
+function script checkclientversion {
+ if (ClientVersion > 20) return;
+
+ mesn "Narrator";
+ mes col("Warning.", 9);
+ mes col("Warning.", 9);
+ mes col("Warning: You are using an old client.", 9);
+ next;
+ mes col("Not all features will work.", 9);
+ next;
+ mes col("Please install the new client from http://www.evolonline.org/ or http://manaplus.org/", 9);
+ next;
+ return;
+}
diff --git a/npc/functions/confused-tree-dict.txt b/npc/functions/confused-tree-dict.txt
new file mode 100644
index 000000000..4250ec35d
--- /dev/null
+++ b/npc/functions/confused-tree-dict.txt
@@ -0,0 +1,560 @@
+// Evol scripts.
+// Author:
+// gumi
+// rein
+// Based on CrazyTree, originally made by:
+// gumi
+// pclouds
+// veryape
+// wushin
+// Description:
+// dictionaries for confused tree
+
+// Built-in variables:
+// ~t lowercase hot word regex
+// ~n npc name
+// ~p player name or special name
+// ~P player name only
+//
+// Custom variables:
+// {{var}} random from array .D_var$
+// {{^var}} same but capitalize
+// {{+var}} same but title case
+// {{!var}} same but all caps
+// You can also specify multiple variables, separated by a comma (,)
+//
+// Example:
+// "*drops a {{! size }} {{ color }} {{^ sizeable object, someone }} on ~p's head*"
+
+function script TREE_dictionaries {
+ .npc$ = strnpcinfo(0);
+
+ // special aliases below (regex of lowercase char names)
+ // the substitutions are an array separated by backticks (`)
+ // XXX: this could become a hashtable at some point if it gets too big
+
+ setarray getvariableofnpc(.alias$[0], .npc$),
+ "^veryape(?:gm)?$", "hairyape",
+
+ "^wu-?shin$", "Dwarven Princess`"
+ "She-Ra",
+
+ "^reid$", "Borg Queen`"
+ "Mistress`"
+ "Milady`"
+ "R'eid",
+
+ "^(?:slicer|madcamel)$", "Camel Toe",
+
+ "^4144(?:4d494e)?$", "NPC",
+
+ "^omatt$", "@@https://youtu.be/S2qiZoqH9OY|omatt@@`"
+ "o'matt",
+
+ "^prsm$", "Refractor`"
+ "Overlord";
+ set getvariableofnpc(.alias, .npc$), getarraysize(getvariableofnpc(.alias$, .npc$));
+
+
+
+ // special drops below (regex of lowercase char names)
+ // the substitutions are an array of standard replies separated by backticks (`)
+ // and allow {{variables}}
+ // XXX: this could become a hashtable at some point if it gets too big
+
+ setarray getvariableofnpc(.sdrops$[0], .npc$),
+ "^reid$", "*drops an empty jar of Nutella on ~p*",
+ "^omatt$", "*drops Elisabeth Granneman on ~p*";
+ set getvariableofnpc(.sdrops, .npc$), getarraysize(getvariableofnpc(.sdrops$, .npc$));
+
+
+ // variables below
+
+ setarray getvariableofnpc(.D_size$[0], .npc$), // {{size}}
+ "tiny",
+ "small",
+ "perfectly sized",
+ "large",
+ "huge",
+ "humongous",
+ "ginormous";
+ set getvariableofnpc(.D_size, .npc$), getarraysize(getvariableofnpc(.D_size$, .npc$));
+
+ setarray getvariableofnpc(.D_color$[0], .npc$), // {{color}}
+ "red",
+ "orange",
+ "yellow",
+ "pink",
+ "aqua",
+ "cyan",
+ "blue",
+ "indigo",
+ "violet",
+ "purple",
+ "magenta",
+ "pink",
+ "black",
+ "white",
+ "grey",
+ "greyscale",
+ "brown",
+ "maroon",
+ "turquoise",
+ "lime",
+ "sky blue",
+ "invisible";
+ set getvariableofnpc(.D_color, .npc$), getarraysize(getvariableofnpc(.D_color$, .npc$));
+
+ setarray getvariableofnpc(.D_violentadverb$[0], .npc$), // {{violent adverb}}
+ "violently",
+ "repeatedly",
+ "casually",
+ "forcefully",
+ "slowly",
+ "carefully",
+ "hopefully",
+ "dangerously",
+ "shockingly",
+ "religiously";
+ set getvariableofnpc(.D_violentadverb, .npc$), getarraysize(getvariableofnpc(.D_violentadverb$, .npc$));
+
+ setarray getvariableofnpc(.D_hello$[0], .npc$), // {{hello}}
+ "hi",
+ "hi",
+ "hi",
+ "hi",
+ "hey",
+ "hey",
+ "hey",
+ "yo",
+ "yo",
+ "hello",
+ "hello",
+ "hello",
+ "hello",
+ "hello",
+ "hello",
+ "hello",
+ "hello",
+ "hello",
+ "hello",
+ "howdy",
+ "bonjour";
+ set getvariableofnpc(.D_hello, .npc$), getarraysize(getvariableofnpc(.D_hello$, .npc$));
+
+ setarray getvariableofnpc(.D_violentverb$[0], .npc$), // {{violent verb}}
+ "slaps",
+ "slaps",
+ "slaps",
+ "slaps",
+ "slaps", // yeah the tree likes to slap a lot
+ "hits",
+ "pummels",
+ "beats",
+ "flattens",
+ "taunts",
+ "liquidates",
+ "spanks",
+ "affronts",
+ "tranquilizes",
+ "atomizes",
+ "impales",
+ "dismembers";
+ set getvariableofnpc(.D_violentverb, .npc$), getarraysize(getvariableofnpc(.D_violentverb$, .npc$));
+
+ setarray getvariableofnpc(.D_location$[0], .npc$), // {{location}}
+ "Artis",
+ "Hurnscald",
+ "Tulimshar",
+ "Nivalis",
+ "Candor",
+ "Drasil";
+ set getvariableofnpc(.D_location, .npc$), getarraysize(getvariableofnpc(.D_location$, .npc$));
+
+ setarray getvariableofnpc(.D_sizeableobject$[0], .npc$), // {{sizeable object}}
+ "trout",
+ "whale",
+ "space whale",
+ "penguin",
+ "coelacanth",
+ "squid",
+ "shrimp",
+ "crab",
+ "tentacle",
+ "dictionary",
+ "grammar book",
+ "textbook",
+ "dinosaur",
+ "t-rex",
+ "star-nosed mole",
+ "chimpanzee",
+ "mermaid",
+ "merman",
+ "piano",
+ "prince",
+ "princess",
+ "pinkie",
+ "squirrel",
+ "mouboo",
+ "wet mop",
+ "drunken pirate",
+ "cake",
+ "cookie",
+ "chocobo",
+ "restraining order",
+ "freight train",
+ "carnival hammer",
+ "crate",
+ "bomb",
+ "bowl of petinuas",
+ "box",
+ "platypus",
+ "magic eightball",
+ "vase";
+ set getvariableofnpc(.D_sizeableobject, .npc$), getarraysize(getvariableofnpc(.D_sizeableobject$, .npc$));
+
+ setarray getvariableofnpc(.D_nsizeableobject$[0], .npc$), // {{n sizeable object}}
+ "octopus",
+ "elephant",
+ "angry cat",
+ "anvil",
+ "encyclopedia set";
+ set getvariableofnpc(.D_nsizeableobject, .npc$), getarraysize(getvariableofnpc(.D_nsizeableobject$, .npc$));
+
+ setarray getvariableofnpc(.D_someone$[0], .npc$), // {{someone}}
+ "Voldemort",
+ "Cthulhu",
+ "Platyna",
+ "Hitler",
+ "Luvia",
+ "General Krukan",
+ "Borg Queen",
+ "Freeyorp",
+ "MadCamel";
+ set getvariableofnpc(.D_someone, .npc$), getarraysize(getvariableofnpc(.D_someone$, .npc$));
+
+ // replies below
+
+ setarray getvariableofnpc(.greetings$[0], .npc$),
+ "{{^ hello }} ~p!",
+ "{{^ hello }} ~p!",
+ "{{^ hello }} ~p!",
+ "{{^ hello }} ~p!",
+ "{{^ hello }} ~p.",
+ "{{^ hello }} ~p.",
+ "{{^ hello }} ~p.",
+ "{{^ hello }} ~p.",
+ "{{^ hello }} ~p.",
+ "{{^ hello }} ~p.",
+ "{{^ hello }} ~p, what's up?",
+ "{{^ hello }} ~p, anything new?",
+ "{{^ hello }} ~p, how are you?",
+ "~p!!!!",
+ "~p!!!",
+ "~p!!",
+ "{{^ hello }} ~p! You are looking lovely today!",
+ "Welcome back, ~p.",
+ "Welcome back, ~p.",
+ "Welcome back, ~p.",
+ "~p is back!!",
+ "Hello and welcome to the Aperture Science computer-aided enrichment center.",
+ "Greetings ~p.",
+ "What's up ~p?",
+ "What's up ~p?",
+ "How are you ~p?";
+ set getvariableofnpc(.greetings, .npc$), getarraysize(getvariableofnpc(.greetings$, .npc$));
+
+ setarray getvariableofnpc(.jokes$[0], .npc$),
+ "How did the tree get drunk? On root beer.",
+ "Do you think I'm lazy?",
+ "I miss CrazyTree %%S.",
+ "I miss LazyTree %%S.",
+ "I'm not telling you!",
+ "*sighs.*",
+ "If I do it for you, then I have to do it for everybody.",
+ "What did the beaver say to the tree? It's been nice gnawing you.",
+ "What did the little tree say to the big tree? Leaf me alone.",
+ "What did the tree wear to the pool party? Swimming trunks.",
+ "What do trees give to their dogs? Treets.",
+ "What do you call a tree that only eats meat? Carniforous.",
+ "What do you call a tree who's always envious? Evergreen.",
+ "What is the tree's least favourite month? Sep-timber!",
+ "What kind of tree can fit into your hand? A palm-tree.",
+ "What was the tree's favorite subject in school? Chemistree.",
+ "Why did the leaf go to the doctor? It was feeling green.",
+ "Why doesn't the tree need sudo? Because it has root.",
+ "Why was the cat afraid of the tree? Because of its bark.",
+ "Why was the tree executed? For treeson.",
+ "How do trees get on the internet? They log in.",
+ "Why did the pine tree get into trouble? Because it was being knotty.",
+ "Did you hear the one about the oak tree? It's a corn-y one!",
+ "What do you call a blonde in a tree with a briefcase? Branch Manager.",
+ "How is an apple like a lawyer? They both look good hanging from a tree.",
+ "Why did the sheriff arrest the tree? Because its leaves rustled.",
+ "I'm too tired, ask someone else.",
+ "If you are trying to get me to tell jokes you are barking up the wrong tree!",
+ "You wooden think they were funny anyhow. Leaf me alone!",
+ "What is brown and sticky? A stick.",
+ "What's the best way to carve wood? Whittle by whittle.",
+ "What did the tree do when the bank closed? It started its own branch.",
+ "Do you want a brief explanation of an acorn? In a nutshell, it’s an oak tree.",
+ "A snare drum and a crash cymbal fell out of a tree. *BA-DUM TSSSHH*",
+ "How do you properly identify a dogwood tree? By the bark!",
+ "Where do saplings go to learn? Elementree school.",
+ "Why do trees make great thieves? Sticky fingers.",
+ "What is green, has leaves, and a trunk? A houseplant going on vacation.",
+ "Where can Adansonia trees go for a quick trim? To the baobarber.",
+ "What looks like half a spruce tree? The other half.",
+ "What do you give to a sick citrus tree? Lemon aid.",
+ "What did the tree say to the drill? You bore me.",
+ "What happened to the wooden car with wooden wheels and a wooden engine? It wooden go.",
+ "How do trees keep you in suspense? I'll tell you tomorrow.",
+ "Where do birch trees keep their valuables? In a river bank.",
+ "What kind of stories do giant sequoia trees tell? Tall tales.",
+ "What is the most frustrating thing about being a tree? Having so many limbs and not being able to walk.",
+ "What's black, highly dangerous, and lives in a tree? A crow with a machine gun.",
+ "What kind of wood doesn't float? Natalie Wood.",
+ "Two men passed a sign while looking for work. It was for tree fellers. They said: “what a shame, there are only two of us”.";
+ set getvariableofnpc(.jokes, .npc$), getarraysize(getvariableofnpc(.jokes$, .npc$));
+
+ setarray getvariableofnpc(.healing$[0], .npc$),
+ "Eat an apple, they're good for you.",
+ "If I do it for you, then I have to do it for everybody.",
+ "Oh, go drink a potion or something.",
+ "Whoops! I lost my spellbook.",
+ "No mana.";
+ set getvariableofnpc(.healing, .npc$), getarraysize(getvariableofnpc(.healing$, .npc$));
+
+ setarray getvariableofnpc(.whoami$[0], .npc$),
+ "An undercover GM.",
+ "An exiled GM.",
+ "I'm not telling you!",
+ "I'm a bot! I'll be level 99 one day! Mwahahahaaha!!!111!",
+ "Somebody said I'm a Chinese copy of CrazyTree.",
+ "I am your evil twin.",
+ "I don't remember anything after I woke up! What happened to me?",
+ "I don't know. Why am I here??",
+ "Who are you?",
+ "On the 8th day, God was bored and said 'There will be bots'. So here I am.",
+ "♪ I'm your hell, I'm your dream, I'm nothing in between ♪♪",
+ "♪♪ Aperture Science. We do what we must, because... we can ♪",
+ "I'm just a reincarnation of a copy.";
+ set getvariableofnpc(.whoami, .npc$), getarraysize(getvariableofnpc(.whoami$, .npc$));
+
+ setarray getvariableofnpc(.drops$[0], .npc$),
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops an {{ n sizeable object }} on ~p's head.*",
+ "*drops an {{ n sizeable object }} on ~p's head.*",
+ "*drops {{ someone }} on ~p's head.*",
+ "*drops a coin on ~p's head.*",
+ "*drops a fruit on ~p's head.*",
+ "*drops an apple on ~p's head.*",
+ "*drops an iten on ~p's head.*",
+ "*drops a GM on ~p.*",
+ "*drops a piece of moon rock on ~p's head.*",
+ "*drops a pin on ~p's head.*",
+ "*drops a rock on ~p's head.*",
+ "*drops a tub of paint on ~p's head.*",
+ "*drops a sandworm on ~p.*",
+ "*drops an idea in ~p's head.*",
+ "*drops The Hitchhiker's Guide to the Galaxy on ~p's head.*",
+ "Ouch.",
+ "Ouchy.",
+ "*drops dead.*",
+ "*sighs.*",
+ "Leaf me alone.",
+ "Stop it! I doesn't drop branches, try the Druid tree for once!";
+ set getvariableofnpc(.drops, .npc$), getarraysize(getvariableofnpc(.drops$, .npc$));
+
+ setarray getvariableofnpc(.die$[0], .npc$),
+ "*drops an iten on ~p's head.*",
+ "*drops a piece of moon rock on ~p's head.*",
+ "*drops {{ someone }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops a {{ sizeable object }} on ~p's head.*",
+ "*drops an {{ n sizeable object }} on ~p's head.*",
+ "*drops a {{ size }} {{ sizeable object, n sizeable object }} on ~p's head.*",
+ "*drops a {{ size }} {{ color }} {{ sizeable object, n sizeable object }} on ~p's head.*",
+ "*{{ violent adverb }} {{ violent verb }} ~p.*",
+ "*drops dead.*",
+ "*sighs.*",
+ "Avada Kedavra!",
+ "Make me!",
+ "Never!!",
+ "You die, ~p!",
+ "You die, ~p!",
+ "You die, ~p!",
+ "You die, ~p!",
+ "No!",
+ "In a minute.",
+ "Suuure... I'll get right on it...";
+ set getvariableofnpc(.die, .npc$), getarraysize(getvariableofnpc(.die$, .npc$));
+
+ setarray getvariableofnpc(.poke$[0], .npc$),
+ "*tickles.*";
+ set getvariableofnpc(.poke, .npc$), getarraysize(getvariableofnpc(.poke$, .npc$));
+
+ setarray getvariableofnpc(.disgusting$[0], .npc$),
+ "Ewwwww %%^.";
+ set getvariableofnpc(.disgusting, .npc$), getarraysize(getvariableofnpc(.disgusting$, .npc$));
+
+ setarray getvariableofnpc(.answer$[0], .npc$),
+ "42.",
+ "Kittens.";
+ set getvariableofnpc(.answer, .npc$), getarraysize(getvariableofnpc(.answer$, .npc$));
+
+ setarray getvariableofnpc(.burning$[0], .npc$),
+ "*curses ~p and dies %%c.*",
+ "Help! I'm on fire!",
+ "Oh hot.. hot hot!",
+ "*is glowing.*",
+ "*is flaming.*",
+ "Ehemm. Where are firefighters? I need them now!",
+ "*is so hot!.*",
+ "*slowly catches fire.*",
+ "*trembles with trepidation.*",
+ "*is immune to fire.*";
+ set getvariableofnpc(.burning, .npc$), getarraysize(getvariableofnpc(.burning$, .npc$));
+
+ setarray getvariableofnpc(.kill$[0], .npc$),
+ "*curses ~p and dies %%c.*";
+ set getvariableofnpc(.kill, .npc$), getarraysize(getvariableofnpc(.kill$, .npc$));
+
+ setarray getvariableofnpc(.silly$[0], .npc$),
+ "Hahaha, good one!";
+ set getvariableofnpc(.silly, .npc$), getarraysize(getvariableofnpc(.silly$, .npc$));
+
+ setarray getvariableofnpc(.love$[0], .npc$),
+ "♪♪ and IIII.. will alwayyyys loooovvve youuuuu. ♪♪ %%]",
+ "♪♪ nothing's gonna change my love for you, you oughta know by now how much I love you.. ♪ %%]",
+ "♪ ..and then I go and spoil it all, by saying something stupid like: “I love you.” ♪",
+ "♪ ..won't you find a place for me? somewhere in your heart... ♪♪",
+ "Thank you.",
+ "♪♪ ..I can't love another when my heart is somewhere far away.. ♪",
+ "%%]";
+ set getvariableofnpc(.love, .npc$), getarraysize(getvariableofnpc(.love$, .npc$));
+
+ setarray getvariableofnpc(.dance$[0], .npc$),
+ "I would but I am rooted to the ground.",
+ "Have you ever seen a tree dance before?",
+ "Hahaha, good one!";
+ set getvariableofnpc(.dance, .npc$), getarraysize(getvariableofnpc(.dance$, .npc$));
+
+ setarray getvariableofnpc(.hate$[0], .npc$),
+ "Right back at you!",
+ "Ok...",
+ "*pats ~p, let it go...*",
+ "Hu hu hu, ~p hates me.";
+ set getvariableofnpc(.hate, .npc$), getarraysize(getvariableofnpc(.hate$, .npc$));
+
+ setarray getvariableofnpc(.bye$[0], .npc$),
+ "*waves goodbye to ~p in tears, come back soon!*";
+ set getvariableofnpc(.bye, .npc$), getarraysize(getvariableofnpc(.bye$, .npc$));
+
+ setarray getvariableofnpc(.pain$[0], .npc$),
+ "Ouch.",
+ "Ouchy.",
+ "Argh.",
+ "Eek.",
+ "*howls.*",
+ "*screams.*",
+ "*groans.*",
+ "*cries.*",
+ "*faints.*",
+ "*shrieks.*",
+ "*hides behind itself.*",
+ "%%k",
+ "Why, what did I do to you? %%i";
+ set getvariableofnpc(.pain, .npc$), getarraysize(getvariableofnpc(.pain$, .npc$));
+
+ setarray getvariableofnpc(.eightball$[0], .npc$),
+ "It is possible.",
+ "Yes!",
+ "Of course.",
+ "Naturally.",
+ "Obviously.",
+ "It shall be.",
+ "The outlook is good.",
+ "It is so.",
+ "One would be wise to think so.",
+ "The answer is certainly yes.",
+ "In your dreams.",
+ "I doubt it very much.",
+ "No chance.",
+ "The outlook is very poor.",
+ "Unlikely.",
+ "About as likely as pigs flying.",
+ "You're kidding, right?",
+ "NO!",
+ "NO.",
+ "No.",
+ "Maybe...",
+ "No clue.",
+ "I don't know.",
+ "The outlook is hazy, please ask again later.",
+ "What are you asking me for?",
+ "Come again?",
+ "You know the answer better than I.",
+ "The answer is def-- oooh! shiny thing!",
+ "No idea.",
+ "Perhaps.",
+ "I think it is better not to tell you.",
+ "Error 417: Expectation failed.";
+ set getvariableofnpc(.eightball, .npc$), getarraysize(getvariableofnpc(.eightball$, .npc$));
+
+ setarray getvariableofnpc(.bad$[0], .npc$),
+ "I'm not bad! You are bad!",
+ "OK, I'm bad.",
+ "I'm just a littttle bad.",
+ "Not as bad as the people that made me.";
+ set getvariableofnpc(.bad, .npc$), getarraysize(getvariableofnpc(.bad$, .npc$));
+
+ setarray getvariableofnpc(.no_idea$[0], .npc$),
+ "What?",
+ "What??",
+ "What?",
+ "Whatever.",
+ "Hmm...",
+ "Hmm...",
+ "Huh?",
+ "*yawns.*",
+ "Wait a minute...",
+ "What are you talking about?",
+ "Who are you?",
+ "What about me?",
+ "I don't know what you are talking about",
+ "Excuse me?",
+ "Very interesting.",
+ "Really?",
+ "Go on...",
+ "*scratches its leafy head.*",
+ "*feels a disturbance in the force.*",
+ "%%j",
+ "*senses a disturbance in the force.*",
+ "I'm bored...",
+ "%%U",
+ "%%[";
+ set getvariableofnpc(.no_idea, .npc$), getarraysize(getvariableofnpc(.no_idea$, .npc$));
+
+ setarray getvariableofnpc(.shut_up$[0], .npc$),
+ "*goes hide in a corner %%S.*";
+ set getvariableofnpc(.shut_up, .npc$), getarraysize(getvariableofnpc(.shut_up$, .npc$));
+
+ setarray getvariableofnpc(.climb$[0], .npc$),
+ "*sways violently.*",
+ "*bends all the way to the ground.*",
+ "*creaks and bends.*",
+ "*welcomes those who come to play %%I.*",
+ "*beams with pride.*";
+ set getvariableofnpc(.climb, .npc$), getarraysize(getvariableofnpc(.climb$, .npc$));
+
+ return;
+}
diff --git a/npc/functions/doors.txt b/npc/functions/doors.txt
new file mode 100644
index 000000000..c1b6565ef
--- /dev/null
+++ b/npc/functions/doors.txt
@@ -0,0 +1,59 @@
+// Evol functions.
+// Author:
+// 4144
+// Description:
+// Doors utility functions
+// Variables:
+// none
+
+function script doorTouch {
+ if (getareausers() <= 1)
+ {
+ .dir = 2;
+ stopnpctimer;
+ initnpctimer;
+ }
+ close;
+}
+
+function script doorUnTouch {
+ if (getareausers(.map$) == 0)
+ {
+ .dir = 4;
+ initnpctimer;
+ startnpctimer;
+ }
+ close;
+}
+
+function script doorTimer {
+ stopnpctimer;
+ if (.dir == 2) .dir = 6;
+ if (.dir == 4) .dir = 8;
+ end;
+}
+
+function script doorInit {
+ .distance = 5;
+ .alwaysVisible = true;
+ .sex = G_OTHER;
+ end;
+}
+
+function script open_door {
+ .@door$ = getarg(0);
+ setnpcdir.@door$, 2;
+ sleep 300;
+ setnpcdir .@door$, 6;
+ sleep 300;
+ return 0;
+}
+
+function script close_door {
+ .@door$ = getarg(0);
+ setnpcdir .@door$, 4;
+ sleep 300;
+ setnpcdir .@door$, 8;
+ sleep 300;
+ return 0;
+}
diff --git a/npc/functions/fishing.txt b/npc/functions/fishing.txt
new file mode 100644
index 000000000..3d719ac78
--- /dev/null
+++ b/npc/functions/fishing.txt
@@ -0,0 +1,294 @@
+// Evol functions.
+// Authors:
+// gumi
+// omatt
+// Travolta
+// Description:
+// Fishing functions.
+// Variable
+// .dir
+// DOWN Never try or pulled too late
+// UP Bait dropped
+// LEFT Fish bite bait
+//
+// player log on .dir is DOWN, start by choose bait menu
+// player chooses bait, script addtimer in npc .dir is UP
+// if player pulls before signal npc, bait is lost, set .bait to DOWN goto choose bait
+// if player pulls after pull delay max, bait is lost, set .bait to DOWN goto choose bait
+// npc signal .dir is LEFT
+// player pulls between npc signal and pulls delay max, got the fish, set .dir to DOWN goto choose bait
+
+function script fishing_cleanup {
+ .@npc$ = getarg(0, "");
+ if (.@npc$ == "") end;
+
+ set getvariableofnpc(.char_id, .@npc$), 0; // clean acc id
+ set getvariableofnpc(.account_id, .@npc$), 0; // clean char id
+ set getvariableofnpc(.last_used, .@npc$), gettimetick(2); // set last used time
+ setnpcdir .@npc$, DOWN; // reset direction
+ return;
+}
+
+- script global fishing handler 32767,{
+ end;
+
+OnBite:
+ if (getnpcdir(@fishing_spot$) != UP)
+ end;
+
+ setnpcdir @fishing_spot$, LEFT;
+ @fishing_tick = gettimetick(0);
+ specialeffect(getvariableofnpc(.bite_fx, @fishing_spot$), SELF, playerattached());
+ end;
+
+OnCleanUp:
+ dispbottom l("You waited too long and lost the bait...");
+ specialeffect(getvariableofnpc(.failure_fx, @fishing_spot$), SELF, playerattached()); // event fail
+OnPCLogoutEvent:
+ fishing_cleanup @fishing_spot$;
+ @fishing_spot$ = ""; // unbind fishing npc
+ end;
+}
+
+function script fishing {
+
+///////////////////////////////////////////
+// Var initialization
+
+ .@npc$ = strnpcinfo(0); // the full name of the fishing spot
+
+ .@account_id = getvariableofnpc(.account_id, .@npc$); // the account id of the player using the fishing spot
+ .@char_id = getvariableofnpc(.char_id, .@npc$); // the char id of the player using the fishing spot
+ .@dir = getnpcdir(.@npc$); // direction of the fishing spot
+ .@last_used = getvariableofnpc(.last_used, .@npc$); // when this fishing spot was last used
+ .@baits = getvariableofnpc(.baits, .@npc$); // bait count
+
+ .@rod = getvariableofnpc(.fishing_rod, .@npc$); // the fishing rod required for this spot
+ .@rod = (.@rod ? .@rod : FishingRod);
+
+ .@regen_time = getvariableofnpc(.cooldown, .@npc$); // cooldown for the fishing spot
+ .@regen_time = (.@regen_time ? .@regen_time : 20);
+
+ .@success_fx = getvariableofnpc(.success_fx, .@npc$); // effect to show on success
+ .@success_fx = (.@success_fx ? .@success_fx : 27);
+
+ .@failure_fx = getvariableofnpc(.failure_fx, .@npc$); // effect to show on failure
+ if (.@failure_fx < 1)
+ {
+ .@failure_fx = 28;
+ set getvariableofnpc(.failure_fx, .@npc$), .@failure_fx; // needed by global handler
+ }
+
+ .@initial_fx = getvariableofnpc(.initial_fx, .@npc$); // effect to show when throwing the bait
+ .@initial_fx = (.@initial_fx ? .@initial_fx : 29);
+
+ .@bite_fx = getvariableofnpc(.bite_fx, .@npc$); // effect to show when something bites
+ if (.@bite_fx < 1)
+ {
+ .@bite_fx = 30;
+ set getvariableofnpc(.bite_fx, .@npc$), .@bite_fx; // needed by global handler
+ }
+
+ .@wait_time_min = getvariableofnpc(.wait_time_min, .@npc$); // min amount of time to wait for the line to sink
+ .@wait_time_min = (.@wait_time_min ? .@wait_time_min : 4000);
+
+ .@wait_time_max = getvariableofnpc(.wait_time_max, .@npc$); // max amount of time to wait for the line to sink
+ .@wait_time_max = (.@wait_time_max ? .@wait_time_max : 18000);
+
+ .@catch_time = getvariableofnpc(.catch_time, .@npc$); // the player must catch the fish within X ms after the line sinks
+ .@catch_time = (.@catch_time ? .@catch_time : 5000);
+
+ .@pull_rand_max = getvariableofnpc(.pull_rand_max, .@npc$);
+ .@pull_rand_max = (.@pull_rand_max ? .@pull_rand_max : 800);
+
+ .@fish_id = getvariableofnpc(.common_fish, .@npc$);
+ .@fish_id = (.@fish_id ? .@fish_id : CommonCarp);
+
+ .@rare_id = getvariableofnpc(.rare_fish, .@npc$);
+ .@rare_fish = (.@rare_fish ? .@rare_fish : GrassCarp);
+
+ .@rare_fish_chance = getvariableofnpc(.rare_fish_chance, .@npc$);
+ .@rare_fish_chance = (.@rare_fish_chance ? .@rare_fish_chance : 25);
+
+ if (getvariableofnpc(.bait_ids[0], .@npc$) < 1)
+ {
+ // default baits (bait, chance booster)
+ setarray getvariableofnpc(.bait_ids[0], .@npc$),
+ SmallTentacles, 0,
+ Bread, 0,
+ Aquada, 1,
+ UrchinMeat, 0,
+ TortugaTongue, 2,
+ Tentacles, 0;
+ }
+
+ if (.@baits < 1)
+ {
+ // only count it once
+ .@baits = getarraysize(getvariableofnpc(.bait_ids[0], .@npc$));
+ set getvariableofnpc(.baits, .@npc$), .@baits;
+ }
+
+
+///////////////////////////////////////////
+// Logic below
+
+ if (countitem(.@rod) < 1)
+ {
+ dispbottom l("You don't have any @@.", getitemlink(.@rod));
+ return -1;
+ }
+
+ if (.@account_id > 0 && !isloggedin(.@account_id, .@char_id))
+ {
+ fishing_cleanup .@npc$; // reset
+ .@dir = DOWN;
+ }
+
+ if (.@char_id != getcharid(CHAR_ID_CHAR) && .@dir != DOWN)
+ {
+ dispbottom l("This fishing spot is already being used!");
+ return -2;
+ }
+
+
+ // pull too soon
+ if (.@dir == UP)
+ {
+ deltimer "global fishing handler::OnCleanUp"; // cancel auto cleanup
+ deltimer "global fishing handler::OnBite";
+ specialeffect(.@failure_fx, SELF, playerattached()); // event fail
+ fishing_cleanup .@npc$; // do it manually instead
+ dispbottom l("You pulled too soon and lost the bait.");
+ return -3;
+ }
+
+ // pull maybe on time
+ else if (.@dir == LEFT)
+ {
+ deltimer "global fishing handler::OnCleanUp"; // cancel auto cleanup
+ fishing_cleanup .@npc$; // do it manually instead
+
+ getmapxy .@mapbis$, .@xbis, .@ybis, UNITTYPE_PC; // get current char location
+
+ // Leave spot, lost the bait
+ if (.@mapbis$ != @fishing_loc$[0] || .@xbis != @fishing_loc[0] || .@ybis != @fishing_loc[1] || @fishing_spot$ != .@npc$)
+ {
+ dispbottom l("You left your fishing spot!");
+ return -4;
+ }
+
+ // RNG to obtain a rare fish
+ // TODO: chance booster
+ if (rand(.@rare_fish_chance) == 0)
+ {
+ // TODO: rare fish array
+ .@fish_id = .@rare_id;
+ }
+ // TODO: else common fish array
+
+ // RNG to obtain a fish
+ if (rand(gettimetick(0) - @fishing_tick) <= .@pull_rand_max)
+ {
+ specialeffect(.@success_fx, SELF, playerattached()); // event success
+
+ if(!checkweight(.@fish_id, 1))
+ {
+ dispbottom l("You caught a @@ but had no room in your inventory to carry it.", getitemlink(.@fish_id));
+ makeitem .@fish_id, 1, .@mapbis$, .@xbis, .@ybis; // drop on the ground
+ return 0;
+ }
+
+ //dispbottom l("You caught a @@!", getitemlink(.@fish_id)); <= already shows "you picked up [...]"
+ getitem .@fish_id, 1;
+ }
+ else
+ {
+ dispbottom l("You pulled too late and lost the bait...");
+ specialeffect(.@failure_fx, SELF, playerattached()); // event fail
+ .@fish_id = 0;
+ }
+
+ return .@fish_id;
+ }
+
+
+
+ if (gettimetick(2) - .@last_used < .@regen_time)
+ {
+ dispbottom l("This fishing spot has just been used, give it a rest.");
+ return -5;
+ }
+
+
+ // begin fishing
+ narrator S_LAST_NEXT,
+ l("You see some fish reflecting the sun on the surface of the water."),
+ l("What will be the bait for the fish?");
+
+ mes "##B" + l("Drag and drop an item from your inventory.") + "##b";
+
+ .@bait = requestitem();
+ .@bait_c = false;
+
+ if (.@bait < 1)
+ {
+ narrator S_FIRST_BLANK_LINE,
+ l("You take your fishing rod and leave.");
+
+ return -6;
+ }
+
+ if (countitem(.@bait) < 1)
+ {
+ return -6;
+ }
+
+ for (.@i = 0; .@i < .@baits; .@i += 2)
+ {
+ if (getvariableofnpc(.bait_ids[.@i], .@npc$) == .@bait)
+ {
+ .@bait_c = true;
+ break;
+ }
+ }
+
+ if (.@bait_c != true)
+ {
+ narrator S_FIRST_BLANK_LINE,
+ l("This item cannot be used as bait here.");
+
+ return -6;
+ }
+
+ if (getvariableofnpc(.char_id, .@npc$) > 0)
+ {
+ narrator S_FIRST_BLANK_LINE,
+ l("Somebody took your place on this spot!"),
+ l("You take your fishing rod and leave.");
+ return -8;
+ }
+
+ @fishing_spot$ = .@npc$; // bind player to fishing spot
+ set getvariableofnpc(.account_id, .@npc$), getcharid(CHAR_ID_ACCOUNT); // record account id
+ set getvariableofnpc(.char_id, .@npc$), getcharid(CHAR_ID_CHAR); // record char id
+ set getvariableofnpc(.last_used, .@npc$), gettimetick(2);
+ getmapxy(@fishing_loc$[0], @fishing_loc[0], @fishing_loc[1], 0); // record char pos
+ delitem .@bait, 1;
+
+ // The player uses this spot, his bait is ready, he just has to wait for the signal.
+ closedialog;
+
+ specialeffect(.@initial_fx, SELF); // throw the bait
+ sleep2 800; // wait 0.8s for synchronize the sound of "plop" in water with the npc dir UP.
+ setnpcdir .@npc$, UP;
+
+ dispbottom l("Wait for the bait to sink underwater.");
+
+ .@delay = rand(.@wait_time_min, .@wait_time_max);
+
+ addtimer .@delay, "global fishing handler::OnBite"; // bite logic
+ addtimer (.@delay + .@catch_time), "global fishing handler::OnCleanUp"; // auto clean up
+
+ return 0;
+}
diff --git a/npc/functions/game-rules.txt b/npc/functions/game-rules.txt
new file mode 100644
index 000000000..f633ee5f3
--- /dev/null
+++ b/npc/functions/game-rules.txt
@@ -0,0 +1,59 @@
+// Evol scripts.
+// Authors:
+// gumi
+// Qwerty Dragon
+// Reid
+// WildX
+// Description:
+// 7 main rules of Evol Online.
+
+function script GameRules {
+ if (checkweight(BookOfLaws, 1) == true && countitem(BookOfLaws) < 1)
+ getitem BookOfLaws, 1; // give the book if the player lost it
+
+ narrator getarg(0, 0),
+ l("1. ##BDo not bot##b, this means you are not allowed to perform any AFK (away from keyboard) activity, apart from standing idle."),
+ l("2. ##BDo not use offensive/rude language##b in the chats or in your character(s) name(s)."),
+ l("3. ##BDo not spam/flood other players.##b This includes chat spam and spam by trade requests."),
+ l("4. ##BSpeak only English in public areas.##b You can speak whatever language you want through whispers or whenever everyone in the area can speak said language."),
+ l("5. ##BDo not beg others##b for money, items or favours of any kind. If you want to ask for something, do it politely and only once. Try not to annoy other players."),
+ l("6. ##BFollow the [@@http://wiki.evolonline.org/rules/esc|ESC@@]##b (Evol Social Convention)."),
+ l("7. ##BDo not multibox.##b You are not allowed to engage in combat while controlling more than one character at a time.");
+ return;
+}
+
+
+- script @rules 32767,{
+ end;
+
+ function read_book {
+ narrator S_FIRST_BLANK_LINE | S_LAST_NEXT,
+ l("This book outlines the laws of every city and holding in Gasaron."),
+ l("The first page contains the universal rules that have been agreed upon throughout the land.");
+
+ GameRules S_NO_NPC_NAME | S_LAST_NEXT;
+
+ narrator S_NO_NPC_NAME,
+ l("The next page begins to list the complex trading laws of the City of Esperia"),
+ l("All this seems unimportant to you right now.");
+ close;
+ }
+
+OnCall:
+ GameRules;
+ close;
+
+OnUseBook:
+ if (openbook())
+ read_book;
+ bye;
+
+OnShelfUse:
+ if (openbookshelf())
+ read_book;
+ bye;
+
+OnInit:
+ .book_name$ = "The Book of Laws";
+ bindatcmd "rules", "@rules::OnCall", 0, 2, 0;
+}
diff --git a/npc/functions/goodbye.txt b/npc/functions/goodbye.txt
new file mode 100644
index 000000000..620883b8c
--- /dev/null
+++ b/npc/functions/goodbye.txt
@@ -0,0 +1,152 @@
+// Evol functions.
+// Authors:
+// gumi
+// Reid
+// Description:
+// script terminator functions
+
+
+
+// goodbye_msg
+// Tell a random goodbye sentence.
+// Variables:
+// .@rand = Random number between the number of "goodbye" choice.
+
+function script goodbye_msg {
+ setarray .byemsg$[0],
+ l("See you!"),
+ l("See you later!"),
+ l("See you soon!"),
+ l("Bye!"),
+ l("Farewell."),
+ l("Bye then!"),
+ l("Goodbye."),
+ l("Bye for now."),
+ l("Talk to you soon!"),
+ l("Talk to you later!"),
+ l("Have a good day!"),
+ l("Cheers!"),
+ l("Take care!");
+
+ return .byemsg$[rand(getarraysize(.byemsg$))];
+}
+
+
+
+// cwarp
+// Closes the dialog, then warps the player.
+// You almost always want to use this instead of `warp`.
+// usage:
+// cwarp;
+// cwarp x, y;
+// cwarp map, x, y;
+
+function script cwarp {
+ .@map$ = getarg(0, "");
+ .@x = getarg(1, 0);
+ .@y = getarg(2, 0);
+
+ if (getargcount() > 0 && getargcount() < 3)
+ {
+ .@npc$ = strnpcinfo(0);
+ .@map$ = getvariableofnpc(.map$, .@npc$);
+ .@x = getarg(0);
+ .@y = getarg(1);
+ }
+
+ getmapxy .@pc_map$, .@pc_x, .@pc_y, UNITTYPE_PC; // get char location
+
+ closedialog; // XXX: maybe send closeclientdialog in the future
+
+ if (getargcount() < 1)
+ {
+ warp .@pc_map$, .@pc_x, .@pc_y; // no arguments, just refresh
+ close;
+ }
+
+ if (.@map$ == .@pc_map$)
+ {
+ if (.@pc_x == .@x && .@pc_y == .@y)
+ {
+ close; // same location, don't move
+ }
+
+ else
+ {
+ slide .@x, .@y; // same map, slide instead of full warp
+ close;
+ }
+ }
+
+ warp .@map$, .@x, .@y; // different map, warp to given location
+ close;
+}
+
+
+
+// cshop
+// closes the dialog, then opens a shop
+// if no npc is given, calls "#<npc> $"
+
+function script cshop {
+ closedialog; // XXX: maybe send closeclientdialog in the future
+ shop getarg(0, "#" + strnpcinfo(0) + " $");
+ //close; => the shop buildin already sends close, and is a terminator itself
+}
+
+
+
+// cstorage
+// closes the dialog, then opens storage
+
+function script cstorage {
+ closedialog; // XXX: maybe send closeclientdialog in the future
+ openstorage;
+ close;
+}
+
+
+
+// bye
+// closes the dialog without waiting for the player to press close
+// can also display an emote
+
+function script bye {
+ .@emote = getarg(0, -1);
+ closedialog; // XXX: maybe send closeclientdialog in the future
+
+ if (.@emote >= 0)
+ emotion .@emote;
+
+ close;
+}
+
+
+
+// goodbye
+// same as bye, but also displays a canned message
+// can also display an emote
+
+function script goodbye {
+ npctalkonce(goodbye_msg());
+ bye getarg(0, -1);
+}
+
+
+
+// goodbye2
+// Waits for the player to press close, displays a canned message,
+// ends execution.
+// Can also display an emote
+
+function script goodbye2 {
+ .@emote = getarg(0, -1);
+
+ close2;
+ npctalkonce(goodbye_msg());
+
+ if (.@emote >= 0)
+ emotion .@emote;
+
+ end;
+}
diff --git a/npc/functions/hammocks.txt b/npc/functions/hammocks.txt
new file mode 100644
index 000000000..8e1c2fec4
--- /dev/null
+++ b/npc/functions/hammocks.txt
@@ -0,0 +1,50 @@
+// Evol functions.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Hammocks utility functions
+// Variables:
+// none
+
+function script hamTouchLeft {
+ if (getareausers() <= 1)
+ {
+ .dir = 0;
+ stopnpctimer;
+ initnpctimer;
+ }
+ close;
+}
+
+function script hamUnTouch {
+ if (getareausers() == 0)
+ {
+ .dir = 2;
+ initnpctimer;
+ startnpctimer;
+ }
+ close;
+}
+
+function script hamTimerLeft {
+ stopnpctimer;
+ if (.dir == 2) .dir = 0;
+ end;
+}
+
+function script hamTouchRight {
+ if (getareausers() <= 1)
+ {
+ .dir = 0;
+ stopnpctimer;
+ initnpctimer;
+ }
+ close;
+}
+
+function script hamTimerRight {
+ stopnpctimer;
+ if (.dir == 2) .dir = 0;
+ end;
+}
diff --git a/npc/functions/harbours.txt b/npc/functions/harbours.txt
new file mode 100644
index 000000000..63d58076b
--- /dev/null
+++ b/npc/functions/harbours.txt
@@ -0,0 +1,39 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Harbour utility functions
+// Animation:
+// Length: 1680
+// Values:
+// 2 Hook moving down.
+// 4 Hook moving up.
+// 6 Hook down.
+// 8 Hook up.
+
+function script harbourClic {
+ if (.dir == 0)
+ {
+ .dir = 2;
+
+ initnpctimer;
+ startnpctimer;
+ close;
+ }
+
+ if (.dir == 6)
+ {
+ .dir = 4;
+
+ initnpctimer;
+ startnpctimer;
+ close;
+ }
+}
+
+function script harbourTimer {
+ stopnpctimer;
+ if (.dir == 2) .dir = 6;
+ if (.dir == 4) .dir = 0;
+ end;
+}
diff --git a/npc/functions/hello.txt b/npc/functions/hello.txt
new file mode 100644
index 000000000..9399b3b58
--- /dev/null
+++ b/npc/functions/hello.txt
@@ -0,0 +1,23 @@
+// Evol functions.
+// Author:
+// Reid
+// Description:
+// Tell a random greeting sentence.
+
+function script hello {
+
+ switch (rand(3))
+ {
+ case 0:
+ npctalkonce(l("Heya!"));
+ break;
+ case 1:
+ npctalkonce(l("Hi."));
+ break;
+ case 2:
+ npctalkonce(l("Nice day to you."));
+ break;
+ }
+
+ return;
+}
diff --git a/npc/functions/input.txt b/npc/functions/input.txt
new file mode 100644
index 000000000..cf0382d25
--- /dev/null
+++ b/npc/functions/input.txt
@@ -0,0 +1,66 @@
+// Evol functions.
+// Author:
+// 4144
+// Description:
+// Input utility functions
+// Variables:
+// none
+
+function script menuint {
+ deletearray .@vals;
+ .@menustr$ = "";
+ .@cnt = 0;
+
+ for (.@f = 0; .@f < getargcount(); .@f = .@f + 2)
+ {
+ if (getarg(.@f) != "")
+ {
+ .@menustr$ = .@menustr$ + getarg(.@f) + ":";
+ .@vals[.@cnt] = getarg(.@f + 1);
+ .@cnt ++;
+ }
+ }
+
+ .@vals[.@cnt] = -1;
+ @menu = 255;
+ @menuret = -1;
+ select(.@menustr$);
+ if (@menu == 255)
+ return -1;
+
+ @menu --;
+ if (@menu < 0 || @menu >= getarraysize(.@vals) - 1)
+ return -1;
+
+ @menuret = .@vals[@menu];
+ return @menuret;
+}
+
+function script menustr {
+ deletearray .@vals$;
+ .@menustr$ = "";
+ .@cnt = 0;
+
+ for (.@f = 0; .@f < getargcount(); .@f = .@f + 2)
+ {
+ if (getarg(.@f) != "")
+ {
+ .@menustr$ = .@menustr$ + getarg(.@f) + ":";
+ .@vals$[.@cnt] = getarg(.@f + 1);
+ .@cnt ++;
+ }
+ }
+
+ @menu = 255;
+ @menuret = -1;
+ select(.@menustr$);
+ if (@menu == 255)
+ return "";
+
+ @menu --;
+ if (@menu < 0 || @menu >= getarraysize(.@vals$))
+ return "";
+
+ @menuret$ = .@vals$[@menu];
+ return @menuret$;
+}
diff --git a/npc/functions/inventoryplace.txt b/npc/functions/inventoryplace.txt
new file mode 100644
index 000000000..4a5e08cad
--- /dev/null
+++ b/npc/functions/inventoryplace.txt
@@ -0,0 +1,37 @@
+// Evol functions.
+// Authors:
+// Qwerty Dragon
+// Reid
+// Description:
+// Check if the player have enough place on his inventory to accept new items with arguments:
+// getarg(even numbers) item ID,
+// getarg(odd numbers) number of items,
+
+function script inventoryplace {
+
+ .@argc = getargcount();
+
+ if (.@argc % 2 != 0)
+ {
+ debugmes "inventoryplace: Wrong argument count.";
+ close;
+ }
+
+ for (.@i = .@j = 0; .@i < .@argc; .@i += 2)
+ {
+ setarray .@item[.@j], getarg(.@i);
+ setarray .@amount[.@j], getarg(.@i + 1);
+ ++.@j;
+ }
+
+ if (!checkweight2(.@item, .@amount))
+ {
+ narrator S_FIRST_BLANK_LINE,
+ l("It looks like you can't carry anything else for now."),
+ l("You should come back when you have some free space.");
+
+ close;
+ }
+
+ return true;
+}
diff --git a/npc/functions/legiontalk.txt b/npc/functions/legiontalk.txt
new file mode 100644
index 000000000..fbc35e1f7
--- /dev/null
+++ b/npc/functions/legiontalk.txt
@@ -0,0 +1,66 @@
+// Evol functions.
+// Authors:
+// Akko Teru
+// Reid
+// Qwerty Dragon
+// Description:
+// Tell a random sentence suited to Aemil's Legion in Artis.
+
+function script legiontalk {
+
+ switch (rand(15))
+ {
+ case 0:
+ npctalkonce(l("Do I look like a tree? I feel like one."));
+ //speech(
+ // l("Do you feel too weak even to do damage to this areas wishy-washy wildlife?"),
+ // l("Then concentrate your anger upon the trees hereabouts, you will gain experience whilst leveling your sword skill on them."),
+ // l("Oh, and a fruit may even fall for you if you are lucky! But stay alert to pick up your drops."));
+ //close;
+ break;
+ case 1:
+ npctalkonce(l("I'm a little busy right now."));
+ break;
+ case 2:
+ npctalkonce(l("Not in the mood to chat."));
+ break;
+ case 3:
+ npctalkonce(l("My breath smells bad."));
+ break;
+ case 4:
+ npctalkonce(l("Don't distract me, I have to stay alert."));
+ break;
+ case 5:
+ npctalkonce(l("Give me some space."));
+ break;
+ case 6:
+ npctalkonce(l("Can you please go away?"));
+ break;
+ case 7:
+ npctalkonce(l("Can't talk right now, I'm on patrol duty."));
+ break;
+ case 8:
+ npctalkonce(l("What're you looking at?!"));
+ break;
+ case 9:
+ npctalkonce(l("I can't stay here and talk all day. I have a job to do."));
+ break;
+ case 10:
+ npctalkonce(lg("Keep moving girl.", "Keep moving boy."));
+ break;
+ case 11:
+ npctalkonce(lg("So you think you're tough? A warrior must also be loyal and patient."));
+ break;
+ case 12:
+ emotion E_LOOKAWAY;
+ break;
+ case 13:
+ npctalkonce(l("Practice! There are no secrets to becoming a warrior."));
+ break;
+ case 14:
+ npctalkonce(l("There is no honor in fighting a weak opponent."));
+ break;
+ }
+
+ return;
+}
diff --git a/npc/functions/main.txt b/npc/functions/main.txt
new file mode 100644
index 000000000..243ae383d
--- /dev/null
+++ b/npc/functions/main.txt
@@ -0,0 +1,215 @@
+// Evol functions.
+// Authors:
+// 4144
+// Travolta
+// Description:
+// Build in functions.
+
+function script menuimage {
+ return getarg(0) + "|" + getarg(1);
+}
+
+function script menuaction {
+ return "[" + getarg(0) + "]";
+}
+
+function script mesn {
+ if (getargcount() > 0)
+ {
+ .@s$ = "[" + getarg(0) + "]";
+ }
+ else
+ {
+ .@s$ = "[" + strnpcinfo(1) + "]";
+ }
+ mes .@s$;
+ return;
+}
+
+function script mesq {
+ mes "\"" + getarg(0)+ "\"";
+ return;
+}
+
+function script g {
+ return Sex == 0 ? getarg(0) : getarg(1);
+}
+
+function script col {
+ .@color = getarg(1);
+ if (.@color < 0) .@color = 0;
+ if (.@color > 9) .@color = 9;
+ return "##" + .@color + getarg(0) + "##0";
+}
+
+function script adddefaultskills {
+ if (getskilllv(NV_BASIC) < 6)
+ {
+ skill NV_BASIC, 6, 0;
+ }
+ return;
+}
+
+function script addremovemapmask {
+ setmapmask getarg(0), (getmapmask(getarg(0)) | (getarg(1) + getarg(2))) ^ getarg(2);
+ return;
+}
+
+// Function to show narrator text. Accepts string args.
+// If first arg is a number N, then it represents bit flags.
+// Bit flags :
+// 0x1 -- blank line at beginning
+// 0x2 -- blank line at the end
+// 0x4 -- use last "next;"
+// 0x8 -- don't use first "mesn;"
+function script narrator {
+ .@start = 0;
+ .@argc = getargcount();
+ .@flags = 0;
+
+ if (.@argc > 1 && !isstr(getarg(0)))
+ {
+ .@start = 1;
+ .@flags = getarg(0);
+ }
+
+ if (.@flags & 0x1)
+ mes "";
+
+ if (!(.@flags & 0x8))
+ mesn l("Narrator");
+
+ for (.@i = .@start; .@i < .@argc; .@i++)
+ {
+ mes col(getarg(.@i), 9);
+ if (.@i < .@argc - 1)
+ next;
+ }
+
+ if (.@flags & 0x4)
+ next;
+ else if (.@flags & 0x2)
+ mes "";
+
+ return;
+}
+
+// Function to show NPC speech. Accepts string args.
+// If first arg is a number N, then it represents bit flags.
+// Bit flags :
+// 0x1 -- blank line at beginning
+// 0x2 -- blank line at the end
+// 0x4 -- use last "next;"
+// 0x8 -- don't use first "mesn;"
+function script speech {
+ .@start = 0;
+ .@argc = getargcount();
+ .@flags = 0;
+
+ if (.@argc > 1 && !isstr(getarg(0)))
+ {
+ .@start = 1;
+ .@flags = getarg(0);
+ }
+
+ if (.@flags & 0x1)
+ mes "";
+
+ if (!(.@flags & 0x8))
+ mesn;
+
+ for (.@i = .@start; .@i < .@argc; .@i++)
+ {
+ mesq getarg(.@i);
+
+ if (.@i < .@argc - 1)
+ next;
+ }
+
+ if (.@flags & 0x4)
+ next;
+ else if (.@flags & 0x2)
+ mes "";
+
+ return;
+}
+
+// Show debug message if .debug variable of NPC is set to 1
+function script npcdebug {
+ if (getvariableofnpc(.debug, strnpcinfo(3)))
+ debugmes strnpcinfo(3) + ": " + getarg(0);
+ return;
+}
+
+function script askyesno {
+ return select(menuaction(l("Yes")),
+ menuaction(l("No")));
+}
+
+// Argument:
+// 0 Quest variable
+// 1 Current value
+// 2 Next value
+function script compareandsetq {
+ if (getq(getarg(0)) == getarg(1))
+ {
+ setq getarg(0), getarg(2);
+ return true;
+ }
+ return false;
+}
+
+// Use a delay to prevent spams from NPC that display text without the
+// use of (a) close/next function(s).
+// Argument:
+// 0 Text to display
+// 1 Lock delay (default = 1)
+// 2 Message function: (default = 0)
+// 0 = npctalk3
+// 1 = npctalk
+// 2 = message
+function script npctalkonce {
+ // lock mechanism
+ switch (getarg(2, 0))
+ {
+ case 1:
+ if (gettimetick(2) <= getvariableofnpc(.talk_lock, strnpcinfo(NPC_NAME_UNIQUE)))
+ return false;
+ set(getvariableofnpc(.talk_lock, strnpcinfo(NPC_NAME_UNIQUE)), gettimetick(2) + getarg(1, 1));
+ break;
+ default:
+ if (gettimetick(2) <= @NPC_TALK_LOCK[getnpcid(0)])
+ return false;
+ @NPC_TALK_LOCK[getnpcid(0)] = gettimetick(2) + getarg(1, 1);
+ }
+
+ // talk mechanism
+ switch (getarg(2, 0))
+ {
+ case 0: npctalk3(getarg(0)); break;
+ case 1: npctalk(getarg(0)); break;
+ case 2: message(strcharinfo(0), getarg(0));
+ }
+
+ return true;
+}
+
+function script getquestlink {
+ return "[@@q" + getarg(0) + "|@@]";
+}
+
+function script getmonsterlink {
+ return "[@@m" + getarg(0) + "|@@]";
+}
+
+function script getpetlink {
+ return "[@@p" + getarg(0) + "|@@]";
+}
+
+function script getmercenarylink {
+ return "[@@M" + getarg(0) + "|@@]";
+}
+
+function script gethomunculuslink {
+ return "[@@h" + getarg(0) + "|@@]";
+}
diff --git a/npc/functions/marriage.txt b/npc/functions/marriage.txt
new file mode 100644
index 000000000..d9e48bf54
--- /dev/null
+++ b/npc/functions/marriage.txt
@@ -0,0 +1,293 @@
+// Evol functions.
+// Author:
+// 4144
+// Description:
+// Functions for marriage
+
+// check is player is near marriage npc
+// args:
+// 0 - player name
+// returns:
+// true if player located near npc.
+function script marriagecheckname {
+ .@name$ = getarg(0);
+ if (.@name$ == "")
+ {
+ // no other registrand
+ return false;
+ }
+ .@id = getcharid(0, .@name$);
+ .@accoundId = getcharid(3, .@name$);
+ if (isloggedin(.@accoundId, .@id) == false)
+ {
+ // registrant not logged in
+ return false;
+ }
+ getmapxy(.@mapname$, .@x, .@y, 0, .@name$);
+ if (.@mapname$ != strnpcinfo(4))
+ {
+ // registrant on other map
+ return false;
+ }
+ if (distance(.@x, .@y, .x, .y) > .distance)
+ {
+ // registrant too far
+ return false;
+ }
+ return true;
+}
+
+// return player name registered with same gender like attached player
+function script getmarriageregistrant {
+ if (Sex)
+ {
+ .@name$ = getvariableofnpc(.maleName$, strnpcinfo(3));
+ }
+ else
+ {
+ .@name$ = getvariableofnpc(.femaleName$, strnpcinfo(3));
+ }
+ return .@name$;
+}
+
+// return registered marriage partner name
+function script getmarriagepartner {
+ if (Sex)
+ {
+ .@name$ = getvariableofnpc(.femaleName$, strnpcinfo(3));
+ }
+ else
+ {
+ .@name$ = getvariableofnpc(.maleName$, strnpcinfo(3));
+ }
+ if (marriagecheckname(.@name$))
+ return .@name$;
+ return "";
+}
+
+// register attached player as partner for marriage
+function script marriageregisterself {
+ if (Sex)
+ {
+ set getvariableofnpc(.maleName$, strnpcinfo(3)), strcharinfo(0);
+ set getvariableofnpc(.maleName_partner$, strnpcinfo(3)), "";
+ }
+ else
+ {
+ set getvariableofnpc(.femaleName$, strnpcinfo(3)), strcharinfo(0);
+ set getvariableofnpc(.femaleName_partner$, strnpcinfo(3)), "";
+ }
+ return;
+}
+
+// return player name what was accepted by partner
+function script getmarriagepartneraccepted {
+ if (Sex)
+ {
+ .@name$ = getvariableofnpc(.femaleName_partner$, strnpcinfo(3));
+ }
+ else
+ {
+ .@name$ = getvariableofnpc(.maleName_partner$, strnpcinfo(3));
+ }
+ return .@name$;
+}
+
+// return true if partner present near and partner accepted you
+function script ismarriagepartneraccepted {
+ .@partner$ = getmarriagepartner();
+ if (.@partner$ == "")
+ return false;
+ .@name$ = getmarriagepartneraccepted();
+ if (.@name$ == strcharinfo(0))
+ return true;
+ return false;
+}
+
+// accept for attached player his/her partner
+// args:
+// 0 - partner name
+function script marriageacceptpartner {
+ .@name$ = getarg(0);
+ if (Sex)
+ {
+ set getvariableofnpc(.maleName_partner$, strnpcinfo(3)), .@name$;
+ }
+ else
+ {
+ set getvariableofnpc(.femaleName_partner$, strnpcinfo(3)), .@name$;
+ }
+ return;
+}
+
+function script askmarry {
+ speech l("Do you want to marry @@?", getarg(0));
+ if (askyesno() == ASK_YES)
+ return true;
+ return false;
+}
+
+// start marriage registration process
+function script marriageregister {
+ .@partner$ = getmarriagepartner();
+ if (.@partner$ == "")
+ { // no partner registered
+ speech l("Ok I add your name... @@...", strcharinfo(0));
+ marriageregisterself();
+ next;
+ speech lg("Now wait for your partner, then talk to me again.");
+ npctalk l("@@ registered for marriage. Waiting for partner...", strcharinfo(0));
+ close;
+ }
+ else
+ { // partner already registered
+ if (askmarry(.@partner$) == true)
+ {
+ marriageregisterself();
+ marriageacceptpartner(.@partner$);
+ npctalk l("@@ registered for marriage and accepted partner @@!", strcharinfo(0), .@partner$);
+ npctalk l("Waiting for @@...", .@partner$);
+ close;
+ }
+ else
+ {
+ close;
+ }
+ }
+ return;
+}
+
+// remove all marriage registations
+function script marriageclear {
+ set getvariableofnpc(.maleName$, strnpcinfo(3)), "";
+ set getvariableofnpc(.femaleName$, strnpcinfo(3)), "";
+ set getvariableofnpc(.maleName_partner$, strnpcinfo(3)), "";
+ set getvariableofnpc(.femaleName_partner$, strnpcinfo(3)), "";
+ return;
+}
+
+// do actual marriage
+function script domarriage {
+ .@name$ = strcharinfo(0);
+ .@partner$ = getarg(0);
+ if (marriage(.@partner$))
+ {
+ speech l("You got married to @@!", .@partner$);
+ npctalk l("@@ and @@ just got married!", .@name$, .@partner$);
+ }
+ else
+ {
+ npctalk l("Marriage failed.");
+ }
+ marriageclear();
+ return;
+}
+
+// marry main code
+function script marriagemarry {
+ .@registrant$ = getmarriageregistrant();
+ if (marriagecheckname(.@registrant$) == true)
+ {
+ if (.@registrant$ == strcharinfo(0))
+ {
+ if (ismarriagepartneraccepted())
+ {
+ .@partner$ = getmarriagepartner();
+ if (marriagecheckname(.@partner$) == false)
+ {
+ speech l("Partner not ready.");
+ }
+ else if (askmarry(.@partner$) == true)
+ {
+ domarriage(.@partner$);
+ }
+ }
+ else
+ {
+ speech l("You already registered. Waiting for your partner...");
+ }
+ }
+ else
+ {
+ speech l("Sorry, I'm busy with other registrations."),
+ l("Come after a little while.");
+ }
+ close;
+ }
+
+ speech l("What can I do for you?");
+ switch (select(l("I want to register for marriage."),
+ l("Nothing")))
+ {
+ case 1:
+ marriageregister;
+ break;
+ case 2:
+ break;
+ }
+ return;
+}
+
+// divorce main code
+function script marriagedivorce {
+ speech l("What can I do for you?");
+ switch (select(l("I want to divorce."),
+ l("Nothing")))
+ {
+ case 1:
+ speech lg("Are you sure?");
+ if (askyesno() == ASK_YES)
+ {
+ if (divorce())
+ {
+ speech l("You are now divorced!"),
+ l("Good look.");
+ npctalk l("@@ divorced!", strcharinfo(0));
+ }
+ else
+ {
+ speech l("Divorce error!");
+ }
+ }
+ break;
+ case 2:
+ break;
+ }
+ return;
+}
+
+// main function for marriage
+function script marriagemain {
+ if (Sex > 1)
+ {
+ speech l("Sorry i can't help you. Go away!");
+ close;
+ }
+
+ if (getpartnerid() != 0)
+ { // have partner
+ marriagedivorce();
+ }
+ else
+ { // no partner
+ marriagemarry();
+ }
+
+ return;
+}
+
+// check registration list by timer
+function script marriagecheck {
+ .@name$ = getvariableofnpc(.maleName$, strnpcinfo(3));
+ if (.@name$ != "" && marriagecheckname(.@name) == false)
+ {
+ set getvariableofnpc(.maleName$, strnpcinfo(3)), "";
+ set getvariableofnpc(.maleName_partner$, strnpcinfo(3)), "";
+ }
+ .@name$ = getvariableofnpc(.femaleName$, strnpcinfo(3));
+ if (.@name$ != "" && marriagecheckname(.@name) == false)
+ {
+ set getvariableofnpc(.femaleName$, strnpcinfo(3)), "";
+ set getvariableofnpc(.femaleName_partner$, strnpcinfo(3)), "";
+ }
+}
diff --git a/npc/functions/masks.txt b/npc/functions/masks.txt
new file mode 100644
index 000000000..98e8bdf87
--- /dev/null
+++ b/npc/functions/masks.txt
@@ -0,0 +1,68 @@
+// Evol functions.
+// Author:
+// Reid
+// Description:
+// Triggers functions to add and remove masks.
+// Variables:
+// none
+
+// Artis Aemil's Legion
+
+function script artisALRemTopMask {
+ if ((getareausers("001-2-33", 23, 27, 45, 31) >= 1) ||
+ (getareausers("001-2-33", 23, 32, 26, 38) >= 1) ||
+ (getareausers("001-2-33", 42, 32, 45, 38) >= 1))
+ {
+ removemapmask "001-2-33", 4;
+ }
+ return 0;
+}
+
+function script artisALAddTopMask {
+ if ((getareausers("001-2-33", 23, 27, 45, 31) == 0) &&
+ (getareausers("001-2-33", 23, 32, 26, 38) == 0) &&
+ (getareausers("001-2-33", 42, 32, 45, 38) == 0))
+ {
+ addmapmask "001-2-33", 4;
+ }
+ return 0;
+}
+
+function script artisALRemBotMask {
+ if (getareausers("001-2-33", 23, 32, 45, 46) >= 1)
+ {
+ removemapmask "001-2-33", 8;
+ }
+ return 0;
+}
+
+function script artisALAddBotMask {
+ if (getareausers("001-2-33", 23, 32, 45, 46) == 0)
+ {
+ addmapmask "001-2-33", 8;
+ }
+ return 0;
+}
+
+function script artisALUpdateMask {
+ if (getareausers("001-2-33", 23, 32, 45, 46) >= 1)
+ {
+ removemapmask "001-2-33", 8;
+ }
+ else
+ {
+ addmapmask "001-2-33", 8;
+ }
+ if ((getareausers("001-2-33", 23, 27, 45, 31) >= 1) ||
+ (getareausers("001-2-33", 23, 32, 26, 38) >= 1) ||
+ (getareausers("001-2-33", 42, 32, 45, 38) >= 1))
+ {
+ removemapmask "001-2-33", 4;
+ }
+ else
+ {
+ addmapmask "001-2-33", 4;
+ }
+
+ return 0;
+}
diff --git a/npc/functions/math.txt b/npc/functions/math.txt
new file mode 100644
index 000000000..004125c7b
--- /dev/null
+++ b/npc/functions/math.txt
@@ -0,0 +1,40 @@
+// Evol functions.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Math functions
+
+
+// abs(<int>)
+// returns the absolute value of the passed integer
+
+function script abs {
+ .@n = getarg(0);
+ return .@n >= 0 ? .@n : -.@n;
+}
+
+
+
+// lognbaselvl({<multiplicator>{, <min value>}})
+// returns BaseLevel * logn (BaseLevel * alpha).
+
+function script lognbaselvl {
+ .@alpha = getarg(0, 1);
+ .@min = getarg(1, 1);
+ .@ret = 0;
+ .@pc_level = BaseLevel * .@alpha;
+
+ while (.@pc_level >>= 1)
+ {
+ ++.@ret;
+ }
+ .@ret *= BaseLevel;
+
+ if (.@ret <= .@min)
+ {
+ .@ret = .@min;
+ }
+
+ return .@ret;
+}
diff --git a/npc/functions/mouboofunc.txt b/npc/functions/mouboofunc.txt
new file mode 100644
index 000000000..6129c083e
--- /dev/null
+++ b/npc/functions/mouboofunc.txt
@@ -0,0 +1,89 @@
+// Evol functions.
+// Author:
+// Reid
+// Description:
+// Various scripts used in walking mouboo NPCs.
+
+function script moubootalk {
+ switch (rand(4))
+ {
+ case 0:
+ npctalkonce(l("Moooooo!"));
+ break;
+ case 1:
+ npctalkonce(l("Moo!"));
+ break;
+ case 2:
+ npctalkonce(l("Moooooooooooo!"));
+ break;
+ case 3:
+ npctalkonce(l("Moooo!"));
+ break;
+ }
+ return;
+}
+
+function script mouboocheckxy {
+ setarray .nearnpc$[0], "Mouboo#Artis0",
+ "Mouboo#Artis1",
+ "Mouboo#Artis2",
+ "Mouboo#Artis3",
+ "Taree";
+ for (.@size = 0; .@size < getarraysize(.nearnpc$); .@size++)
+ {
+ if (strcmp(.name$, .nearnpc$[.@size]) == 0)
+ {
+ continue;
+ }
+
+ .@npc_x = getvariableofnpc(.x, .nearnpc$[.@size]);
+ .@npc_y = getvariableofnpc(.y, .nearnpc$[.@size]);
+
+ if (.@npc_x == .x && .@npc_y == .y)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+function script moubootimer {
+ if (mouboocheckxy() && !isunitwalking())
+ {
+ movetonextpoint;
+ }
+ else if (rand(0,6) == 5)
+ {
+ if (!isunitwalking())
+ {
+ movetonextpoint;
+ }
+ }
+ initnpctimer;
+ end;
+}
+
+function script mouboograph {
+ initmovegraph "down_pos", 66, 79, 75, 86,
+ "left_pos", 66, 79, 75, 86,
+ "up_pos", 66, 79, 75, 86,
+ "right_pos", 66, 79, 75, 86;
+
+ setmovegraphcmd "down_pos", "left_pos", 1, "dir 2",
+ "down_pos", "up_pos", 1, "dir 4",
+ "down_pos", "right_pos", 1, "dir 6",
+ "left_pos", "down_pos", 1, "dir 0",
+ "left_pos", "up_pos", 1, "dir 4",
+ "left_pos", "right_pos", 1, "dir 6",
+ "up_pos", "down_pos", 1, "dir 0",
+ "up_pos", "left_pos", 1, "dir 2",
+ "up_pos", "right_pos", 1, "dir 6",
+ "right_pos", "down_pos", 1, "dir 0",
+ "right_pos", "left_pos", 1, "dir 2",
+ "right_pos", "up_pos", 1, "dir 4";
+
+ firstmove "wait 2", "down_pos";
+ initnpctimer;
+ end;
+}
diff --git a/npc/functions/npcmove.txt b/npc/functions/npcmove.txt
new file mode 100644
index 000000000..eb6acded0
--- /dev/null
+++ b/npc/functions/npcmove.txt
@@ -0,0 +1,142 @@
+// Evol functions.
+// Author:
+// 4144
+// Description:
+// Moving npc utility functions
+// Variables:
+// none
+
+function script initpath {
+ deletearray getvariableofnpc(.movepathcmd$, strnpcinfo(3));
+ deletearray getvariableofnpc(.movepathy, strnpcinfo(3));
+ deletearray getvariableofnpc(.movepathx, strnpcinfo(3));
+ .@cnt = 0;
+
+ for (.@f = 0; .@f < getargcount(); .@f = .@f + 3)
+ {
+ set getvariableofnpc(.movepathcmd$[.@cnt], strnpcinfo(3)), getarg(.@f);
+ set getvariableofnpc(.movepathx[.@cnt], strnpcinfo(3)), getarg(.@f + 1);
+ set getvariableofnpc(.movepathy[.@cnt], strnpcinfo(3)), getarg(.@f + 2);
+ .@cnt ++;
+ }
+ //debugmes "array size: " + str(getarraysize(getvariableofnpc(.movepath, strnpcinfo(3))));
+ return;
+}
+
+function script domoveaction {
+ //debugmes "domoveaction: " + str(getvariableofnpc(.movepos, strnpcinfo(3)));
+ .@pos = getvariableofnpc(.movepos, strnpcinfo(3));
+ if (.@pos >= getarraysize(getvariableofnpc(.movepathx, strnpcinfo(3))) || .@pos < 0)
+ return;
+ //debugmes "walking";
+ .@cmd$ = getvariableofnpc(.movepathcmd$[.@pos], strnpcinfo(3));
+ //debugmes "cmd: " + .@cmd$;
+
+ if (.@cmd$ == "move")
+ {
+ npcwalkto getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)), getvariableofnpc(.movepathy[.@pos], strnpcinfo(3));
+ }
+ else if (.@cmd$ == "dir")
+ {
+ setnpcdir getvariableofnpc(.movepathx[.@pos], strnpcinfo(3));
+ return 2;
+ }
+ else if (.@cmd$ == "wait")
+ {
+ set getvariableofnpc(.waitticks, strnpcinfo(3)), getvariableofnpc(.movepathx[.@pos], strnpcinfo(3));
+ }
+ else if (.@cmd$ == "emote")
+ {
+ unitemote getnpcid(0), getvariableofnpc(.movepathx[.@pos], strnpcinfo(3));
+ return 2;
+ }
+ else if (.@cmd$ == "class")
+ {
+ .class = getvariableofnpc(.movepathx[.@pos], strnpcinfo(3));
+ return 2;
+ }
+ else if (.@cmd$ == "warp")
+ {
+ movenpc strnpcinfo(3), getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)), getvariableofnpc(.movepathy[.@pos], strnpcinfo(3));
+ }
+ else if (.@cmd$ == "goto")
+ {
+ set getvariableofnpc(.movepos, strnpcinfo(3)), getvariableofnpc(.movepathx[.@pos], strnpcinfo(3));
+ return 0;
+ }
+ else if (.@cmd$ == "rmove")
+ {
+ getmapxy(.@mapName$, .@x, .@y, 1);
+ npcwalkto .@x + getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)), .@y + getvariableofnpc(.movepathy[.@pos], strnpcinfo(3));
+ }
+ else if (.@cmd$ == "speed")
+ {
+ .speed = getvariableofnpc(.movepathx[.@pos], strnpcinfo(3));
+ return 2;
+ }
+ else if (.@cmd$ == "sit")
+ {
+ npcsit;
+ }
+ else if (.@cmd$ == "stand")
+ {
+ npcstand;
+ }
+ return 1;
+}
+
+function script movetonextpos {
+ .@wait = getvariableofnpc(.waitticks, strnpcinfo(3));
+ if (.@wait > 0)
+ {
+ .@wait --;
+ //debugmes "wait";
+ set getvariableofnpc(.waitticks, strnpcinfo(3)), .@wait;
+ return;
+ }
+ .@true = 1;
+ while (.@true)
+ {
+ .@true = 0;
+ .@pos = getvariableofnpc(.movepos, strnpcinfo(3));
+ //debugmes "movetonextpos: " + str(.@pos);
+ .@res = domoveaction(.@pos);
+ if (.@res == 1 || .@res == 2)
+ {
+ .@pos++;
+ if (.@pos >= getarraysize(getvariableofnpc(.movepathx, strnpcinfo(3))))
+ .@pos = 0;
+ set getvariableofnpc(.movepos, strnpcinfo(3)), .@pos;
+ }
+ if (.@res == 0 || .@res == 2)
+ {
+ .@true = 1;
+ }
+ }
+ return;
+}
+
+function script initialmove {
+ set getvariableofnpc(.movepos, strnpcinfo(3)), 0;
+ set getvariableofnpc(.waitticks, strnpcinfo(3)), -1;
+ movetonextpos;
+ return;
+}
+
+function script getmovecmd {
+ .@pos = getvariableofnpc(.movepos, strnpcinfo(3));
+ if (.@pos >= getarraysize(getvariableofnpc(.movepathx, strnpcinfo(3))) || .@pos < 0)
+ return "";
+ return getvariableofnpc(.movepathcmd$[.@pos], strnpcinfo(3));
+}
+
+function script domovestep {
+ if (isunitwalking())
+ {
+ initnpctimer;
+ end;
+ }
+ movetonextpos;
+ initnpctimer;
+ end;
+}
diff --git a/npc/functions/npcmovegraph.txt b/npc/functions/npcmovegraph.txt
new file mode 100644
index 000000000..b26f9a162
--- /dev/null
+++ b/npc/functions/npcmovegraph.txt
@@ -0,0 +1,485 @@
+// Evol functions.
+// Author:
+// Travolta
+// Description:
+// Moving npc utility functions (graph-based)
+// Variables:
+// none
+
+function script initmovegraph {
+ deletearray getvariableofnpc(.movegraphcmd$, strnpcinfo(3));
+ deletearray getvariableofnpc(.movegraphlabels$, strnpcinfo(3));
+ deletearray getvariableofnpc(.movegraphweight, strnpcinfo(3));
+ deletearray getvariableofnpc(.movegraphflags, strnpcinfo(3));
+ deletearray getvariableofnpc(.movepos_y1, strnpcinfo(3));
+ deletearray getvariableofnpc(.movepos_x1, strnpcinfo(3));
+ deletearray getvariableofnpc(.movepos_x2, strnpcinfo(3));
+ deletearray getvariableofnpc(.movepos_y2, strnpcinfo(3));
+ .@cnt = 0;
+
+ for (.@f = 0; .@f < getargcount();)
+ {
+ set getvariableofnpc(.movegraphlabels$[.@cnt], strnpcinfo(3)), getarg(.@f++);
+ set getvariableofnpc(.movepos_x1[.@cnt], strnpcinfo(3)), getarg(.@f++);
+ set getvariableofnpc(.movepos_y1[.@cnt], strnpcinfo(3)), getarg(.@f++);
+ if (!isstr(getarg(.@f, "label")))
+ {
+ set getvariableofnpc(.movepos_x2[.@cnt], strnpcinfo(3)), getarg(.@f++);
+ set getvariableofnpc(.movepos_y2[.@cnt], strnpcinfo(3)), getarg(.@f++);
+ }
+ .@cnt ++;
+ }
+ return;
+}
+
+function script findmovegraphlabel {
+ if (!getargcount())
+ {
+ debugmes "findmovegraphlabel: no argument";
+ return -1;
+ }
+ if (!isstr(getarg(0)))
+ {
+ debugmes "findmovegraphlabel: need string argument";
+ return -1;
+ }
+
+ .@arg$ = getarg(0);
+ for (.@i = 0; .@i < getarraysize(getvariableofnpc(.movegraphlabels$, strnpcinfo(3))); .@i++)
+ {
+ if (getvariableofnpc(.movegraphlabels$[.@i], strnpcinfo(3)) == .@arg$)
+ return .@i;
+ }
+
+ npcdebug "findmovegraphlabel: label not found: " + getarg(0);
+ return -1;
+}
+
+/* setmovegraphcmd(fromPositionLabel,toPositionLabel[,moveChanceWeight[,moveFlags]],postCommand, ...);
+ * This function manipulates NPC moving graph. Before calling it, make sure
+ * `initmovegraph' was called. The function accepts 3-5 parameters (many times):
+ * fromPositionLabel, toPositionLabel -- starting and ending position of NPC move
+ * moveChanceWeight -- positive integer, represents the chance of moving in given direction. (optional)
+ * moveFlags -- if .mg_flags & moveFlags != 0, move is possible. (optional)
+ * postCommand -- either "moveon" (start moving to next location straight after arriving from
+ * fromPositionLabel to toPositionLabel) or a semicolon-separated set of commands
+ * ("wait 3", "emote 5" etc, see `execmovecmd') that will be executed after arrival.
+ * The commands don't have to end with ";moveon", it's executed in the end by default.
+ */
+function script setmovegraphcmd {
+ .@size = getarraysize(getvariableofnpc(.movepos_x1, strnpcinfo(3)));
+
+ for (.@f = 0; .@f < getargcount();)
+ {
+ .@from = findmovegraphlabel(getarg(.@f++));
+ .@to = findmovegraphlabel(getarg(.@f++));
+ .@weight = 1;
+ if (!isstr(getarg(.@f)))
+ .@weight = getarg(.@f++);
+ .@flags = 0xffff;
+ if (!isstr(getarg(.@f)))
+ .@flags = getarg(.@f++);
+ .@cmd$ = getarg(.@f++);
+ .@index = .@from * .@size + .@to; // emulation of 2d array
+ set getvariableofnpc(.movegraphcmd$[.@index], strnpcinfo(3)), .@cmd$;
+ set getvariableofnpc(.movegraphweight[.@index], strnpcinfo(3)), .@weight;
+ set getvariableofnpc(.movegraphflags[.@index], strnpcinfo(3)), .@flags;
+ }
+ return;
+}
+
+function script execmovecmd {
+
+ explode(.@cmd$, getarg(0), " ");
+
+ if (.@cmd$[0] == "moveon")
+ {
+ return 0;
+ }
+ else if (.@cmd$[0] == "dir")
+ {
+ .dir = atoi(.@cmd$[1]);
+ }
+ else if (.@cmd$[0] == "sit")
+ {
+ npcsit;
+ }
+ else if (.@cmd$[0] == "stand")
+ {
+ npcstand;
+ }
+ else if (.@cmd$[0] == "wait")
+ {
+ set getvariableofnpc(.waitticks, strnpcinfo(3)), atoi(.@cmd$[1]);
+ return 1;
+ }
+ else if (.@cmd$[0] == "emote")
+ {
+ unitemote getnpcid(0), atoi(.@cmd$[1]);
+ }
+ else if (.@cmd$[0] == "class")
+ {
+ .class = atoi(.@cmd$[1]);
+ }
+ else if (.@cmd$[0] == "warp")
+ {
+ .@pos = -1;
+ .@map$ = "";
+ .@pos_idx = 1;
+ if (getarraysize(.@cmd$) == 3)
+ {
+ .@map$ = .@cmd$[1];
+ .@pos_idx = 2;
+ }
+ .@pos = findmovegraphlabel(.@cmd$[.@pos_idx]);
+ if (.@pos != -1)
+ {
+ .@x = getvariableofnpc(.movepos_x1[.@pos], strnpcinfo(3));
+ .@y = getvariableofnpc(.movepos_y1[.@pos], strnpcinfo(3));
+ if (getstrlen(.@map$) > 0)
+ unitwarp getnpcid(0), .@map$, .@x, .@y;
+ else
+ movenpc strnpcinfo(3), .@x, .@y;
+ set getvariableofnpc(.movepos, strnpcinfo(3)), .@pos;
+ }
+ else
+ {
+ debugmes "execmovecmd: unknown WARP destination label: " + .@cmd$[1];
+ }
+ }
+ else if (.@cmd$[0] == "call")
+ {
+ switch (getarraysize(.@cmd$))
+ {
+ case 1:
+ debugmes "execmovecmd: CALL command needs some parameters";
+ return 0;
+ case 2:
+ return callfunc(.@cmd$[1]);
+ break;
+ case 3:
+ return callfunc(.@cmd$[1], .@cmd$[2]);
+ case 4:
+ default:
+ return callfunc(.@cmd$[1], .@cmd$[2], .@cmd$[3]);
+ }
+ }
+ else if (.@cmd$[0] == "speed")
+ {
+ .speed = atoi(.@cmd$[1]);
+ }
+ else if (.@cmd$[0] == "say")
+ {
+ deletearray .@cmd$[0], 1;
+ npctalk implode(.@cmd$, " ");
+ }
+ else if (.@cmd$[0] == "debugmes")
+ {
+ deletearray .@cmd$[0], 1;
+ debugmes implode(.@cmd$, " ");
+ }
+ else if (.@cmd$[0] == "flags")
+ {
+ set getvariableofnpc(.mg_flags, strnpcinfo(3)), axtoi(.@cmd$[1]);
+ }
+ else if (.@cmd$[0] == "flags_0")
+ {
+ .@flags = getvariableofnpc(.mg_flags, strnpcinfo(3));
+ .@flags &= ~axtoi(.@cmd$[1]);
+ set getvariableofnpc(.mg_flags, strnpcinfo(3)), .@flags;
+ }
+ else if (.@cmd$[0] == "flags_1")
+ {
+ .@flags = getvariableofnpc(.mg_flags, strnpcinfo(3));
+ .@flags |= axtoi(.@cmd$[1]);
+ set getvariableofnpc(.mg_flags, strnpcinfo(3)), .@flags;
+ }
+ else
+ {
+ debugmes "Unknown move graph cmd: " + .@cmd$[0];
+ }
+ return 0;
+}
+
+function script getnextmovecmd {
+ .@cmds$ = getvariableofnpc(.nextcmd$, strnpcinfo(3));
+ .@firstCmd$ = .@cmds$;
+ .@restCmd$ = "moveon";
+ .@index = strpos(.@cmds$, ";");
+ if (.@index >= 0)
+ {
+ .@firstCmd$ = substr(.@cmds$, 0, .@index - 1);
+ .@restCmd$ = substr(.@cmds$, .@index + 1, getstrlen(.@cmds$) - 1);
+ }
+ // npcdebug "firstCmd = " + .@firstCmd$ + " restCmd = " + .@restCmd$;
+ set getvariableofnpc(.nextcmd$, strnpcinfo(3)), .@restCmd$;
+ return strip(.@firstCmd$);
+}
+
+// getrandompoint(x1,y1,x2,y2)
+// -- Get a random walkable point within a map rectangle
+// x1, y1 -- top-left corner of rectangle
+// x2, y2 -- bottom-right corner of rectangle
+// Returns 0 on success and -1 on error;
+// Since we cannot return multiple values, the random
+// coordinates are stored in NPC variables .move__rand_x, .move__rand_y
+function script getrandompoint {
+ if (getargcount() < 4)
+ {
+ debugmes "error: getrandompoint(x1, y1, x2, y2) takes 4 arguments";
+ return -1;
+ }
+
+ .@max_pokes = 10;
+ .@x1 = getarg(0);
+ .@y1 = getarg(1);
+ .@x2 = getarg(2);
+ .@y2 = getarg(3);
+ .@rx = -1; .@ry = -1;
+
+ getmapxy(.@map$, .@cx, .@cy, 1); // npc location
+
+ // let's try max_pokes random cells
+ for (.@poke = 0; .@poke < .@max_pokes; .@poke++)
+ {
+ .@rx = rand(.@x1, .@x2);
+ .@ry = rand(.@y1, .@y2);
+ if (checknpccell(.@map$, .@rx, .@ry, cell_chkpass))
+ goto L_Found;
+ }
+
+ // we check each cell from random middle point to the end
+ for (;.@rx <= .@x2; .@rx++)
+ {
+ for (;.@ry <= .@y2; .@ry++)
+ if (checknpccell(.@map$, .@rx, .@ry, cell_chkpass))
+ goto L_Found;
+ .@ry = .@y1;
+ }
+
+ // we check the rectangle from beginning to end
+ for (.@rx = .@x1; .@rx <= .@x2; .@rx++)
+ for (.@ry = .@y1; .@ry <= .@y2; .@ry++)
+ if (checknpccell(.@map$, .@rx, .@ry, cell_chkpass))
+ goto L_Found;
+
+ // finally, if we don't find anything
+ debugmes "error: getrandompoint: cannot find walkable cell in rectangle [(" + .@x1 + "," + .@y1 + ") , (" + .@x2 + "," + .@y2 + ")]";
+ return -1;
+
+L_Found:
+ set getvariableofnpc(.move__rand_x, strnpcinfo(3)), .@rx;
+ set getvariableofnpc(.move__rand_y, strnpcinfo(3)), .@ry;
+ return 0;
+}
+
+// wrapper function for npcwalkto. It can accept 4 parameters.
+// If #3 and #4 params are set, the walkto location is chosen
+// from rectangle (x1,y1,x2,y2).
+// It sets the npc variables .move_target_x, .move_target_y
+// that are used to resume NPC walking
+// Returns 1 if walking is possible, 0 otherwise;
+function script mg_npcwalkto {
+ if (getargcount() < 2)
+ {
+ debugmes "usage: mg_npcwalkto(x1,y1[,x2,y2])";
+ return -1;
+ }
+
+ .@x = getarg(0);
+ .@y = getarg(1);
+ .@x2 = getarg(2);
+ .@y2 = getarg(3);
+
+ if (getargcount() >= 4 && .@x2 > 0 && .@y2 > 0)
+ if (!getrandompoint(.@x, .@y, .@x2, .@y2))
+ {
+ .@x = getvariableofnpc(.move__rand_x, strnpcinfo(3));
+ .@y = getvariableofnpc(.move__rand_y, strnpcinfo(3));
+ }
+ else
+ return 0;
+
+ if (npcwalkto(.@x, .@y))
+ {
+ set getvariableofnpc(.move_target_x, strnpcinfo(3)), .@x;
+ set getvariableofnpc(.move_target_y, strnpcinfo(3)), .@y;
+ return 1;
+ }
+ return 0;
+}
+
+function script movetonextpoint {
+ .@wait = getvariableofnpc(.waitticks, strnpcinfo(3));
+ if (.@wait > 0)
+ {
+ .@wait--;
+ set getvariableofnpc(.waitticks, strnpcinfo(3)), .@wait;
+ return;
+ }
+
+ .@nextcmd$ = "";
+ while (.@nextcmd$ != "moveon")
+ {
+ .@nextcmd$ = getnextmovecmd();
+ npcdebug " " + .@nextcmd$;
+ if (execmovecmd(.@nextcmd$))
+ return;
+ }
+
+ // choose a random path from all possible paths
+ .@size = getarraysize(getvariableofnpc(.movepos_x1, strnpcinfo(3)));
+ .@pos = getvariableofnpc(.movepos, strnpcinfo(3));
+ .@curr_flags = getvariableofnpc(.mg_flags, strnpcinfo(3));
+ .@cur = 0;
+ .@weight_sum = 0;
+ // .@dbg$ = getvariableofnpc(.movegraphlabels$[.@pos], strnpcinfo(3)) + ": ";
+
+ for (.@i = 0; .@i < .@size; .@i++)
+ {
+ .@index = .@pos * .@size + .@i;
+ .@cmd$ = getvariableofnpc(.movegraphcmd$[.@index], strnpcinfo(3));
+ .@flags = getvariableofnpc(.movegraphflags[.@index], strnpcinfo(3));
+ if (.@cmd$ != "" &&
+ .@curr_flags & .@flags)
+ {
+ .@nextpos[.@cur] = .@i;
+ .@weights[.@cur] = getvariableofnpc(.movegraphweight[.@index], strnpcinfo(3));
+ // .@dbg$ += getvariableofnpc(.movegraphlabels$[.@i], strnpcinfo(3)) + "=" + .@weights[.@cur] + " ";
+ .@weight_sum += .@weights[.@cur];
+ .@cur++;
+ }
+ }
+ // npcdebug .@dbg$;
+
+ if (!.@weight_sum)
+ {
+ npcdebug("error: cannot pick next walk point. flags=" +
+ getvariableofnpc(.mg_flags, strnpcinfo(3)));
+ return;
+ }
+
+ .@pick_tries = 0;
+L_TryPick:
+ // pick a random number based on weight_sum
+ .@rnd = rand(.@weight_sum);
+ .@k = -1; .@weight_sum = 0;
+ while (.@rnd >= .@weight_sum)
+ {
+ .@k++;
+ .@weight_sum += .@weights[.@k];
+ }
+
+ .@next_idx = .@nextpos[.@k];
+ .@next_x1 = getvariableofnpc(.movepos_x1[.@next_idx], strnpcinfo(3));
+ .@next_y1 = getvariableofnpc(.movepos_y1[.@next_idx], strnpcinfo(3));
+ .@next_x2 = getvariableofnpc(.movepos_x2[.@next_idx], strnpcinfo(3));
+ .@next_y2 = getvariableofnpc(.movepos_y2[.@next_idx], strnpcinfo(3));
+
+ if (!mg_npcwalkto(.@next_x1, .@next_y1, .@next_x2, .@next_y2))
+ {
+ if (.@pick_tries < 10)
+ {
+ .@pick_tries++;
+ goto L_TryPick;
+ }
+
+ // move to a nearby position
+ .@x1 = getvariableofnpc(.movepos_x1[.@pos], strnpcinfo(3));
+ .@y1 = getvariableofnpc(.movepos_y1[.@pos], strnpcinfo(3));
+ .@x2 = getvariableofnpc(.movepos_x2[.@pos], strnpcinfo(3));
+ .@y2 = getvariableofnpc(.movepos_y2[.@pos], strnpcinfo(3));
+ mg_npcwalkto(.@x1, .@y1, .@x2, .@y2);
+ set getvariableofnpc(.nextcmd$, strnpcinfo(3)), "wait 1";
+
+ return;
+ }
+
+ if (getvariableofnpc(.debug, strnpcinfo(3)))
+ {
+ getmapxy(.@map$, .@cx, .@cy, 1);
+ .@dist = distance(.@cx, .@cy, .@next_x1, .@next_y1);
+ npcdebug("moving to " + getvariableofnpc(.movegraphlabels$[.@next_idx], strnpcinfo(3)) +
+ " ("+ getvariableofnpc(.move_target_x, strnpcinfo(3)) +
+ "," + getvariableofnpc(.move_target_y, strnpcinfo(3)) +
+ ") [distance=" + .@dist +
+ "] flags=" + getvariableofnpc(.mg_flags, strnpcinfo(3)));
+ }
+
+ .@nextcmd$ = getvariableofnpc(.movegraphcmd$[.@pos * .@size + .@next_idx], strnpcinfo(3));
+ set getvariableofnpc(.nextcmd$, strnpcinfo(3)), .@nextcmd$;
+ set getvariableofnpc(.movepos, strnpcinfo(3)), .@next_idx;
+ return;
+}
+
+// initial actions for npc when using move graphs.
+// function can accept 2 arguments:
+// 1: action sequence, for example "speed 200; dir 4". Default is "moveon"
+// 2: start point label. Default is #0 from move graph labels
+function script firstmove {
+ .@nextcmd$ = getarg(0, "moveon");
+ .@initpos = findmovegraphlabel(getarg(1, ""));
+ if (.@initpos < 0) .@initpos = 0;
+
+ set getvariableofnpc(.movepos, strnpcinfo(3)), .@initpos;
+ movenpc strnpcinfo(3), getvariableofnpc(.movepos_x1[.@initpos], strnpcinfo(3)),
+ getvariableofnpc(.movepos_y1[.@initpos], strnpcinfo(3));
+ set getvariableofnpc(.nextcmd$, strnpcinfo(3)), .@nextcmd$;
+ set getvariableofnpc(.waitticks, strnpcinfo(3)), -1;
+ set getvariableofnpc(.mg_flags, strnpcinfo(3)), 0xffff;
+ movetonextpoint;
+ return;
+}
+
+function script npc_pausemove {
+ stopnpctimer;
+ .@move_after = 0;
+
+ if (isunitwalking())
+ {
+ .@move_after = 1;
+ npcwalkto .x, .y;
+ npcstop;
+ }
+ set getvariableofnpc(.move_after_pause, strnpcinfo(3)), .@move_after;
+
+ return 0;
+}
+
+function script npc_resumemove {
+ startnpctimer;
+
+ if (getvariableofnpc(.move_after_pause, strnpcinfo(3)))
+ {
+ .@x = getvariableofnpc(.move_target_x, strnpcinfo(3));
+ .@y = getvariableofnpc(.move_target_y, strnpcinfo(3));
+ npcwalkto .@x, .@y;
+ }
+
+ return 0;
+}
+
+// npc_turntoxy(x,y)
+// turn npc toward an object at position (x,y)
+function script npc_turntoxy {
+ .@target_x = getarg(0);
+ .@target_y = getarg(1);
+ .@dx = abs(.@target_x - .x);
+ .@dy = abs(.@target_y - .y);
+
+ if (.@dx > .@dy)
+ .dir = .@target_x >= .x ? 6 : 2;
+ else
+ .dir = .@target_y >= .y ? 0 : 4;
+
+ return 0;
+}
+
+function script dographmovestep {
+ if (!isunitwalking())
+ {
+ movetonextpoint;
+ }
+ initnpctimer;
+ end;
+}
diff --git a/npc/functions/openbook.txt b/npc/functions/openbook.txt
new file mode 100644
index 000000000..0278415ce
--- /dev/null
+++ b/npc/functions/openbook.txt
@@ -0,0 +1,36 @@
+// Evol functions.
+// Author:
+// Reid
+// Description:
+// Narrator dialogue to show the selected book.
+// Variables:
+// @book_name$ = The name of the book to read.
+
+function script openbook {
+ .@book_name$ = "\"" + l(getarg(0, getvariableofnpc(.book_name$, strnpcinfo(0)))) + "\"";
+
+ narrator S_LAST_NEXT,
+ l("You open a book named @@.", .@book_name$),
+ l("Do you want to read it?");
+
+ return (select("Yes.", "No.") == 1);
+}
+
+function script openbookshelf {
+ .@book_name$ = "\"" + l(getarg(0, getvariableofnpc(.book_name$, strnpcinfo(0)))) + "\"";
+
+ narrator S_LAST_NEXT,
+ l("You see a dust covered book on the shelf..."),
+ l("The name of the book is @@.", .@book_name$),
+ l("Do you want to read it?");
+
+ return (select("Yes.", "No.") == 1);
+}
+
+function script openoldbook {
+ narrator S_LAST_NEXT,
+ l("You open the book, but it looks like the sea water and time damaged it severely. Some pages are not readable anymore. Some others are simply missing."),
+ l("The old book seems to tell about the legend of Aemil. Would you like to read it?");
+
+ return (select("Yes.", "No.") == 1);
+}
diff --git a/npc/functions/permissions.txt b/npc/functions/permissions.txt
new file mode 100644
index 000000000..62e0da6b7
--- /dev/null
+++ b/npc/functions/permissions.txt
@@ -0,0 +1,35 @@
+// Evol scripts.
+// Author:
+// gumi
+// Description:
+// checks player permissions
+// ** admins are implicitly everything
+
+// administrator
+function script is_admin {
+ return has_permission(PERM_USE_ALL_COMMANDS, getarg(0, getcharid(CHAR_ID_ACCOUNT)));
+}
+
+// any staff member
+function script is_trusted {
+ return is_admin(getarg(0, getcharid(CHAR_ID_ACCOUNT))) ||
+ has_permission("show_client_version", getarg(0, getcharid(CHAR_ID_ACCOUNT)));
+}
+
+// developer
+function script is_dev {
+ return is_admin(getarg(0, getcharid(CHAR_ID_ACCOUNT))) ||
+ has_permission(PERM_RECEIVE_REQUESTS, getarg(0, getcharid(CHAR_ID_ACCOUNT)));
+}
+
+// event coordinator
+function script is_evtc {
+ return is_admin(getarg(0, getcharid(CHAR_ID_ACCOUNT))) ||
+ can_use_command("@monster", getarg(0, getcharid(CHAR_ID_ACCOUNT)));
+}
+
+// game master
+function script is_gm {
+ return is_admin(getarg(0, getcharid(CHAR_ID_ACCOUNT))) ||
+ has_permission("send_gm", getarg(0, getcharid(CHAR_ID_ACCOUNT)));
+}
diff --git a/npc/functions/quest-debug/000-ShipQuests_Julia.txt b/npc/functions/quest-debug/000-ShipQuests_Julia.txt
new file mode 100644
index 000000000..e4e0ec2cd
--- /dev/null
+++ b/npc/functions/quest-debug/000-ShipQuests_Julia.txt
@@ -0,0 +1,37 @@
+// Julia quest debug
+// Author:
+// gumi
+
+function script QuestDebug0 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Julia";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Julia));
+ mes "---";
+ mes l("Related quests:");
+ mes "ShipQuests_Nard: " + getq(ShipQuests_Nard);
+ mes "ShipQuests_ChefGado: " + getq(ShipQuests_ChefGado);
+ mes "General_Narrator: " + getq(General_Narrator);
+ next;
+
+ GenericQuestDebug ShipQuests_Julia,
+ menuimage("actions/manage", l("Debug Nard quest")), -1,
+ menuimage("actions/manage", l("Debug Gado quest")), -2,
+ menuimage("actions/manage", l("Debug Narrator")), -3,
+ l("Does not have the quest"), 0,
+ l("Got the quest"), 1,
+ l("Completed"), 2;
+
+ switch (@menuret)
+ {
+ case -1: callfunc "QuestDebug4"; break;
+ case -2: callfunc "QuestDebug17"; break;
+ case -3: callfunc "QuestDebug28"; break;
+ default: if (@menuret < 0) return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/001-ShipQuests_Arpan.txt b/npc/functions/quest-debug/001-ShipQuests_Arpan.txt
new file mode 100644
index 000000000..26c496466
--- /dev/null
+++ b/npc/functions/quest-debug/001-ShipQuests_Arpan.txt
@@ -0,0 +1,27 @@
+// Arpan quest debug
+// Author:
+// gumi
+
+function script QuestDebug1 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Arpan";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Arpan));
+ next;
+
+ GenericQuestDebug ShipQuests_Arpan,
+ l("Arpan is waiting for you"), 0,
+ l("Arpan told you to open the chest"), 1,
+ l("You opened the chest"), 2,
+ l("Completed"), 3;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/002-ShipQuests_Alige.txt b/npc/functions/quest-debug/002-ShipQuests_Alige.txt
new file mode 100644
index 000000000..36d0ce23e
--- /dev/null
+++ b/npc/functions/quest-debug/002-ShipQuests_Alige.txt
@@ -0,0 +1,27 @@
+// Alige quest debug
+// Author:
+// gumi
+
+function script QuestDebug2 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Alige";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Alige));
+ next;
+
+ GenericQuestDebug ShipQuests_Alige,
+ l("Does not have the quest"), 0,
+ l("First encounter"), 1,
+ l("Alige asks for food"), 2,
+ l("Completed"), 3;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/003-ShipQuests_Peter.txt b/npc/functions/quest-debug/003-ShipQuests_Peter.txt
new file mode 100644
index 000000000..e08e1eb24
--- /dev/null
+++ b/npc/functions/quest-debug/003-ShipQuests_Peter.txt
@@ -0,0 +1,30 @@
+// Peter quest debug
+// Author:
+// gumi
+
+function script QuestDebug3 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Peter";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Peter));
+ next;
+
+ GenericQuestDebug ShipQuests_Peter,
+ l("Does not have the quest"), 0,
+ l("Peter needs help"), 6,
+ l("Peter asks to kill rattos"), 1,
+ l("Killed rattos"), 2,
+ l("Got no reward"), 3,
+ l("Peter asks to kill rattos again"), 4,
+ l("Peter gave reward"), 5;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/004-ShipQuests_Nard.txt b/npc/functions/quest-debug/004-ShipQuests_Nard.txt
new file mode 100644
index 000000000..9ec51cd87
--- /dev/null
+++ b/npc/functions/quest-debug/004-ShipQuests_Nard.txt
@@ -0,0 +1,38 @@
+// Nard quest debug
+// Author:
+// gumi
+
+function script QuestDebug4 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Nard";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Nard));
+ mes "---";
+ mes l("Subquests:");
+ mes "ShipQuests_Gugli: " + getq(ShipQuests_Gugli);
+ mes "ShipQuests_ChefGado: " + getq(ShipQuests_ChefGado);
+ next;
+
+ GenericQuestDebug ShipQuests_Nard,
+ l("Does not have the quest"), 0,
+ l("Nard asks to help crew"), 1,
+ menuimage("actions/manage", l("Debug Gugli quest")), -1,
+ l("Completed Gugli's task"), 2,
+ l("Nard asks to solve conflict"), 3,
+ menuimage("actions/manage", l("Debug Gado quest")), -2,
+ l("Solved conflict"), 4,
+ l("Official crew member"), 5,
+ l("Talked to narrator"), 6;
+
+ switch (@menuret)
+ {
+ case -1: callfunc "QuestDebug16"; break;
+ case -2: callfunc "QuestDebug17"; break;
+ default: if (@menuret < 0) return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/005-ShipQuests_Knife.txt b/npc/functions/quest-debug/005-ShipQuests_Knife.txt
new file mode 100644
index 000000000..a5ec1ae86
--- /dev/null
+++ b/npc/functions/quest-debug/005-ShipQuests_Knife.txt
@@ -0,0 +1,25 @@
+// Knife quest debug
+// Author:
+// gumi
+
+function script QuestDebug5 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Knife";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Knife));
+ next;
+
+ GenericQuestDebug ShipQuests_Knife,
+ l("Does not have the quest"), 0,
+ l("Got the knife"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/006-ShipQuests_ArpanMoney.txt b/npc/functions/quest-debug/006-ShipQuests_ArpanMoney.txt
new file mode 100644
index 000000000..00e2fbea8
--- /dev/null
+++ b/npc/functions/quest-debug/006-ShipQuests_ArpanMoney.txt
@@ -0,0 +1,26 @@
+// Money quest debug
+// Author:
+// gumi
+
+function script QuestDebug6 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_ArpanMoney";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_ArpanMoney));
+ next;
+
+ GenericQuestDebug ShipQuests_ArpanMoney,
+ l("Does not have the quest"), 0,
+ l("Elmo told about money"), 1,
+ l("Arpan gave money"), 2;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/007-ShipQuests_Door.txt b/npc/functions/quest-debug/007-ShipQuests_Door.txt
new file mode 100644
index 000000000..88aa00abe
--- /dev/null
+++ b/npc/functions/quest-debug/007-ShipQuests_Door.txt
@@ -0,0 +1,25 @@
+// Door quest debug
+// Author:
+// gumi
+
+function script QuestDebug7 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Door";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Door));
+ next;
+
+ GenericQuestDebug ShipQuests_Door,
+ l("Does not have the quest"), 0,
+ l("Heard conversation"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/008-ShipQuests_Couwan.txt b/npc/functions/quest-debug/008-ShipQuests_Couwan.txt
new file mode 100644
index 000000000..3df0cdbf0
--- /dev/null
+++ b/npc/functions/quest-debug/008-ShipQuests_Couwan.txt
@@ -0,0 +1,26 @@
+// Couwan quest debug
+// Author:
+// gumi
+
+function script QuestDebug8 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Couwan";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Couwan));
+ next;
+
+ GenericQuestDebug ShipQuests_Couwan,
+ l("Does not have the quest"), 0,
+ l("Couwan asks to deliver box"), 1,
+ l("Delivered box, got reward"), 2;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/009-ShipQuests_TreasureChest.txt b/npc/functions/quest-debug/009-ShipQuests_TreasureChest.txt
new file mode 100644
index 000000000..97adef46f
--- /dev/null
+++ b/npc/functions/quest-debug/009-ShipQuests_TreasureChest.txt
@@ -0,0 +1,25 @@
+// Treasure chest quest debug
+// Author:
+// gumi
+
+function script QuestDebug9 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_TreasureChest";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_TreasureChest));
+ next;
+
+ GenericQuestDebug ShipQuests_TreasureChest,
+ l("Does not have the quest"), 0,
+ l("Opened treasure chest"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/010-ShipQuests_Ale.txt b/npc/functions/quest-debug/010-ShipQuests_Ale.txt
new file mode 100644
index 000000000..e54221224
--- /dev/null
+++ b/npc/functions/quest-debug/010-ShipQuests_Ale.txt
@@ -0,0 +1,25 @@
+// Part of Gugli quest debug
+// Author:
+// gumi
+
+function script QuestDebug10 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Ale";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Ale));
+ next;
+
+ GenericQuestDebug ShipQuests_Ale,
+ l("Does not have the quest"), 0,
+ l("Got the package"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/011-ShipQuests_Astapolos.txt b/npc/functions/quest-debug/011-ShipQuests_Astapolos.txt
new file mode 100644
index 000000000..aca065edb
--- /dev/null
+++ b/npc/functions/quest-debug/011-ShipQuests_Astapolos.txt
@@ -0,0 +1,25 @@
+// Part of Gugli quest debug
+// Author:
+// gumi
+
+function script QuestDebug11 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Astapolos";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Astapolos));
+ next;
+
+ GenericQuestDebug ShipQuests_Astapolos,
+ l("Does not have the quest"), 0,
+ l("Got the package"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/012-ShipQuests_Gulukan.txt b/npc/functions/quest-debug/012-ShipQuests_Gulukan.txt
new file mode 100644
index 000000000..fac7ccded
--- /dev/null
+++ b/npc/functions/quest-debug/012-ShipQuests_Gulukan.txt
@@ -0,0 +1,25 @@
+// Part of Gugli quest debug
+// Author:
+// gumi
+
+function script QuestDebug12 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Gulukan";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Gulukan));
+ next;
+
+ GenericQuestDebug ShipQuests_Gulukan,
+ l("Does not have the quest"), 0,
+ l("Got the package"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/013-ShipQuests_Jalad.txt b/npc/functions/quest-debug/013-ShipQuests_Jalad.txt
new file mode 100644
index 000000000..9ae6ed2a2
--- /dev/null
+++ b/npc/functions/quest-debug/013-ShipQuests_Jalad.txt
@@ -0,0 +1,25 @@
+// Part of Gugli quest debug
+// Author:
+// gumi
+
+function script QuestDebug13 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Jalad";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Jalad));
+ next;
+
+ GenericQuestDebug ShipQuests_Jalad,
+ l("Does not have the quest"), 0,
+ l("Got the package"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/014-ShipQuests_QMuller.txt b/npc/functions/quest-debug/014-ShipQuests_QMuller.txt
new file mode 100644
index 000000000..8a25ee653
--- /dev/null
+++ b/npc/functions/quest-debug/014-ShipQuests_QMuller.txt
@@ -0,0 +1,25 @@
+// Part of Gugli quest debug
+// Author:
+// gumi
+
+function script QuestDebug14 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_QMuller";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_QMuller));
+ next;
+
+ GenericQuestDebug ShipQuests_QMuller,
+ l("Does not have the quest"), 0,
+ l("Got the package"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/015-ShipQuests_Tibbo.txt b/npc/functions/quest-debug/015-ShipQuests_Tibbo.txt
new file mode 100644
index 000000000..84280ebfe
--- /dev/null
+++ b/npc/functions/quest-debug/015-ShipQuests_Tibbo.txt
@@ -0,0 +1,25 @@
+// Part of Gugli quest debug
+// Author:
+// gumi
+
+function script QuestDebug15 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Tibbo";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Tibbo));
+ next;
+
+ GenericQuestDebug ShipQuests_Tibbo,
+ l("Does not have the quest"), 0,
+ l("Got the package"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/016-ShipQuests_Gugli.txt b/npc/functions/quest-debug/016-ShipQuests_Gugli.txt
new file mode 100644
index 000000000..e4868ff48
--- /dev/null
+++ b/npc/functions/quest-debug/016-ShipQuests_Gugli.txt
@@ -0,0 +1,48 @@
+// Part of Gugli quest debug
+// Author:
+// gumi
+
+function script QuestDebug16 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_Gugli";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_Gugli));
+ mes "---";
+ mes l("Subquests:");
+ mes "ShipQuests_Ale: " + getq(ShipQuests_Ale);
+ mes "ShipQuests_Astapolos: " + getq(ShipQuests_Astapolos);
+ mes "ShipQuests_Gulukan: " + getq(ShipQuests_Gulukan);
+ mes "ShipQuests_Jalad: " + getq(ShipQuests_Jalad);
+ mes "ShipQuests_QMuller: " + getq(ShipQuests_QMuller);
+ mes "ShipQuests_Tibbo: " + getq(ShipQuests_Tibbo);
+ next;
+
+ GenericQuestDebug ShipQuests_Gugli,
+ l("Does not have the quest"), 0,
+ l("Gugli asks to collect packages"), 1,
+ menuimage("actions/manage", l("Reset subquests")), -1,
+ menuimage("actions/manage", l("Set subquests as completed")), -2,
+ l("Got reward from gugli"), 2;
+
+ switch (@menuret)
+ {
+ case 0:
+ case 2:
+ case -1:
+ case -2:
+ .@v = (@menuret == -2 || @menuret == 2);
+ setq ShipQuests_Ale, .@v;
+ setq ShipQuests_Astapolos, .@v;
+ setq ShipQuests_Gulukan, .@v;
+ setq ShipQuests_Jalad, .@v;
+ setq ShipQuests_QMuller, .@v;
+ setq ShipQuests_Tibbo, .@v;
+ break;
+ default: if (@menuret < 0) return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/017-ShipQuests_ChefGado.txt b/npc/functions/quest-debug/017-ShipQuests_ChefGado.txt
new file mode 100644
index 000000000..05e8cdb09
--- /dev/null
+++ b/npc/functions/quest-debug/017-ShipQuests_ChefGado.txt
@@ -0,0 +1,30 @@
+// Gado quest debug
+// Author:
+// gumi
+
+function script QuestDebug17 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ShipQuests_ChefGado";
+ mes "---";
+ mes l("Quest state: @@", getq(ShipQuests_ChefGado));
+ next;
+
+ GenericQuestDebug ShipQuests_ChefGado,
+ l("Does not have the quest"), 0,
+ l("Nard asks to solve conflict"), 1,
+ l("Got poison from Gado"), 2,
+ l("Poisoned Julia"), 3,
+ l("Completed, Gado wins"), 4,
+ l("Completed, Julia wins (returned poison)"), 5,
+ l("Completed, Julia wins"), 6;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/018-General_Cookies.txt b/npc/functions/quest-debug/018-General_Cookies.txt
new file mode 100644
index 000000000..16c7bcd75
--- /dev/null
+++ b/npc/functions/quest-debug/018-General_Cookies.txt
@@ -0,0 +1,25 @@
+// Cookie quest debug
+// Author:
+// gumi
+
+function script QuestDebug18 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "General_Cookies";
+ mes "---";
+ mes l("Quest state: @@", getq(General_Cookies));
+ next;
+
+ GenericQuestDebug General_Cookies,
+ l("Does not have the quest"), 0,
+ l("Got a cookie"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/019-ArtisQuests_LazyBrother.txt b/npc/functions/quest-debug/019-ArtisQuests_LazyBrother.txt
new file mode 100644
index 000000000..41733adf8
--- /dev/null
+++ b/npc/functions/quest-debug/019-ArtisQuests_LazyBrother.txt
@@ -0,0 +1,28 @@
+// Lazy brother quest debug
+// Author:
+// gumi
+
+function script QuestDebug19 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ArtisQuests_LazyBrother";
+ mes "---";
+ mes l("Quest state: @@", getq(ArtisQuests_LazyBrother));
+ next;
+
+ GenericQuestDebug ArtisQuests_LazyBrother,
+ l("Does not have the quest"), 0,
+ l("Katja asked for help"), 1,
+ l("Found bobo, didn't tell Katja"), 2,
+ l("Told bobo to go home"), 3,
+ l("Katja gave reward"), 4;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/020-ArtisQuests_Urchin.txt b/npc/functions/quest-debug/020-ArtisQuests_Urchin.txt
new file mode 100644
index 000000000..3a092e478
--- /dev/null
+++ b/npc/functions/quest-debug/020-ArtisQuests_Urchin.txt
@@ -0,0 +1,26 @@
+// Urchin quest debug
+// Author:
+// gumi
+
+function script QuestDebug20 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ArtisQuests_Urchin";
+ mes "---";
+ mes l("Quest state: @@", getq(ArtisQuests_Urchin));
+ next;
+
+ GenericQuestDebug ArtisQuests_Urchin,
+ l("Does not have the quest"), 0,
+ l("Moon needs @@", l("Croc Claw")), 1,
+ l("Found @@, got exp", l("Croc Claw")), 2;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/021-ArtisQuests_CatchPiou.txt b/npc/functions/quest-debug/021-ArtisQuests_CatchPiou.txt
new file mode 100644
index 000000000..f9c45339e
--- /dev/null
+++ b/npc/functions/quest-debug/021-ArtisQuests_CatchPiou.txt
@@ -0,0 +1,26 @@
+// Piou quest debug
+// Author:
+// gumi
+
+function script QuestDebug21 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ArtisQuests_CatchPiou";
+ mes "---";
+ mes l("Quest state: @@", getq(ArtisQuests_CatchPiou));
+ next;
+
+ GenericQuestDebug ArtisQuests_CatchPiou,
+ l("Does not have the quest"), 0,
+ l("Salem asks to catch piou"), 1,
+ l("Returned piou to Salem"), 2;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/022-ArtisQuests_Fishman.txt b/npc/functions/quest-debug/022-ArtisQuests_Fishman.txt
new file mode 100644
index 000000000..0a193e6fe
--- /dev/null
+++ b/npc/functions/quest-debug/022-ArtisQuests_Fishman.txt
@@ -0,0 +1,26 @@
+// Eugene quest debug
+// Author:
+// gumi
+
+function script QuestDebug22 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ArtisQuests_Fishman";
+ mes "---";
+ mes l("Quest state: @@", getq(ArtisQuests_Fishman));
+ next;
+
+ GenericQuestDebug ArtisQuests_Fishman,
+ l("Does not have the quest"), 0,
+ l("Eugene needs tentacles"), 1,
+ l("Gave tentacles, got reward"), 2;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/023-ArtisQuests_QOnan.txt b/npc/functions/quest-debug/023-ArtisQuests_QOnan.txt
new file mode 100644
index 000000000..02eaa8f60
--- /dev/null
+++ b/npc/functions/quest-debug/023-ArtisQuests_QOnan.txt
@@ -0,0 +1,27 @@
+// Q'Onan quest debug
+// Author:
+// gumi
+
+function script QuestDebug23 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ArtisQuests_QOnan";
+ mes "---";
+ mes l("Quest state: @@", getq(ArtisQuests_QOnan));
+ next;
+
+ GenericQuestDebug ArtisQuests_QOnan,
+ l("Does not have the quest"), 0,
+ l("Q'Onan asks to find chest"), 1,
+ l("Found the chest"), 2,
+ l("Gave to Q'Onan, got reward"), 3;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/026-General_Rumly.txt b/npc/functions/quest-debug/026-General_Rumly.txt
new file mode 100644
index 000000000..c533c27a0
--- /dev/null
+++ b/npc/functions/quest-debug/026-General_Rumly.txt
@@ -0,0 +1,27 @@
+// Rumly quest debug
+// Author:
+// gumi
+
+function script QuestDebug26 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "General_Rumly";
+ mes "---";
+ mes l("Quest state: @@", getq(General_Rumly));
+ next;
+
+ GenericQuestDebug General_Rumly,
+ l("Does not have the quest"), 0,
+ l("Rumly needs your help"), 1,
+ l("Rumly wants @@", l("Plushroom")), 2,
+ l("Gave @@ to Rumly", l("Plushroom")), 3;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/027-ArtisQuests_Enora.txt b/npc/functions/quest-debug/027-ArtisQuests_Enora.txt
new file mode 100644
index 000000000..9121ceb30
--- /dev/null
+++ b/npc/functions/quest-debug/027-ArtisQuests_Enora.txt
@@ -0,0 +1,49 @@
+// Newbie quest debug
+// Author:
+// gumi
+
+function script QuestDebug27 {
+ do
+ {
+ clear();
+ setnpcdialogtitle(l("Quest debug"));
+ mes("ArtisQuests_Enora");
+ mes("---");
+ mes(l("Quest state: @@, @@",
+ getq(ArtisQuests_Enora),
+ getq2(ArtisQuests_Enora)));
+ next();
+
+ GenericQuestDebug(ArtisQuests_Enora,
+ l("Does not have the quest"), 0,
+ l("Enora asks to visit Chelios"), 1,
+ l("Chelios asks to visit Lloyd"), 2,
+ l("Lloyd gave package"), 3,
+ l("Chelios made sword"), 4,
+ l("Enora asks to visit Resa"), 5,
+ l("Resa gave package"), 6,
+ l("Enora asks to visit Q'Pid"), 7,
+ l("Lost the riddle"), 8,
+ l("Ivan gave package"), 9,
+ l("Enora asks to kill fluffies"), 10,
+ l("Completed, got reward"), 11);
+
+ switch (@menuret)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10: setq(ArtisQuests_Enora, getq(ArtisQuests_Enora), 0); break;
+ case 11: setq(ArtisQuests_Enora, getq(ArtisQuests_Enora), 10); break;
+ default: if (@menuret < 0) return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/028-General_Narrator.txt b/npc/functions/quest-debug/028-General_Narrator.txt
new file mode 100644
index 000000000..408668b7a
--- /dev/null
+++ b/npc/functions/quest-debug/028-General_Narrator.txt
@@ -0,0 +1,25 @@
+// Narrator debug
+// Author:
+// gumi
+
+function script QuestDebug28 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "General_Narrator";
+ mes "---";
+ mes l("Quest state: @@", getq(General_Narrator));
+ next;
+
+ GenericQuestDebug General_Narrator,
+ l("Game introduction"), 0,
+ l("Visited Artis at least once"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/029-ArtisQuests_Fexil.txt b/npc/functions/quest-debug/029-ArtisQuests_Fexil.txt
new file mode 100644
index 000000000..9c0d7945d
--- /dev/null
+++ b/npc/functions/quest-debug/029-ArtisQuests_Fexil.txt
@@ -0,0 +1,27 @@
+// Fexil quest debug
+// Author:
+// gumi
+
+function script QuestDebug29 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ArtisQuests_Fexil";
+ mes "---";
+ mes l("Quest state: @@", getq(ArtisQuests_Fexil));
+ next;
+
+ GenericQuestDebug ArtisQuests_Fexil,
+ l("Does not have the quest"), 0,
+ l("Lloyd gave pass"), 1,
+ l("Fexil needs help"), 2,
+ l("Fexil wants to buy fur"), 3;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/030-ArtisQuests_Lloyd.txt b/npc/functions/quest-debug/030-ArtisQuests_Lloyd.txt
new file mode 100644
index 000000000..0afb019c8
--- /dev/null
+++ b/npc/functions/quest-debug/030-ArtisQuests_Lloyd.txt
@@ -0,0 +1,25 @@
+// Lloyd quest debug
+// Author:
+// gumi
+
+function script QuestDebug30 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ArtisQuests_Lloyd";
+ mes "---";
+ mes l("Quest state: @@", getq(ArtisQuests_Lloyd));
+ next;
+
+ GenericQuestDebug ArtisQuests_Lloyd,
+ l("Does not have the quest"), 0,
+ l("Registered"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/031-General_Janus.txt b/npc/functions/quest-debug/031-General_Janus.txt
new file mode 100644
index 000000000..f97b4fbeb
--- /dev/null
+++ b/npc/functions/quest-debug/031-General_Janus.txt
@@ -0,0 +1,31 @@
+// Janus quest debug
+// Author:
+// gumi
+
+function script QuestDebug31 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "General_Janus";
+ mes "---";
+ mes l("Quest state: @@", getq(General_Janus));
+ next;
+
+ GenericQuestDebug General_Janus,
+ l("Does not have the quest"), 0,
+ l("Talked to Janus"), 1,
+ l("Can create party"), 2,
+ l("Can create guild"), 3;
+
+ switch (@menuret)
+ {
+ case 0:
+ case 1: skill NV_BASIC, min(6, getskilllv(NV_BASIC)), 0; break;
+ case 2:
+ case 3: skill NV_BASIC, max(7, getskilllv(NV_BASIC)), 0; break;
+ default: if (@menuret < 0) return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/032-ArtisQuests_MonaDad.txt b/npc/functions/quest-debug/032-ArtisQuests_MonaDad.txt
new file mode 100644
index 000000000..68ba67fe9
--- /dev/null
+++ b/npc/functions/quest-debug/032-ArtisQuests_MonaDad.txt
@@ -0,0 +1,25 @@
+// Mona quest debug
+// Author:
+// gumi
+
+function script QuestDebug32 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "ArtisQuests_MonaDad";
+ mes "---";
+ mes l("Quest state: @@", getq(ArtisQuests_MonaDad));
+ next;
+
+ GenericQuestDebug ArtisQuests_MonaDad,
+ l("Does not have the quest"), 0,
+ l("Mona's dad is missing"), 1;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/033-Artis_Legion_Progress.txt b/npc/functions/quest-debug/033-Artis_Legion_Progress.txt
new file mode 100644
index 000000000..c4ea5558a
--- /dev/null
+++ b/npc/functions/quest-debug/033-Artis_Legion_Progress.txt
@@ -0,0 +1,30 @@
+// Mona quest debug
+// Authors:
+// gumi
+// monwarez
+
+function script QuestDebug33 {
+ do
+ {
+ clear;
+ setnpcdialogtitle l("Quest debug");
+ mes "Artis_Legion_Progress";
+ mes "---";
+ mes l("Quest state: @@", getq(Artis_Legion_Progress));
+ next;
+
+ GenericQuestDebug Artis_Legion_Progress,
+ l("Does not have the quest"), 0,
+ l("Sent to training"), 1,
+ l("Finished training"), 2,
+ l("Sent to battle"), 3,
+ l("Finished battle"), 4,
+ l("Sent to Q'Anon"), 5;
+
+ if (@menuret < 0)
+ {
+ return;
+ }
+
+ } while (1);
+}
diff --git a/npc/functions/quest-debug/functions.txt b/npc/functions/quest-debug/functions.txt
new file mode 100644
index 000000000..f89adfab7
--- /dev/null
+++ b/npc/functions/quest-debug/functions.txt
@@ -0,0 +1,109 @@
+// Evol functions.
+// Author:
+// gumi
+// Description:
+// generic quest debug functions
+
+
+
+// GenericQuestDebug
+// makes a generic quest debug menu for the given quest when the server
+// is in debug mode.
+
+function script GenericQuestDebug {
+ if (!debug && !is_admin())
+ {
+ select
+ menuimage("actions/back", l("Go back"));
+
+ @menuret = -0x7FFFFFFF;
+ return 1;
+ }
+
+ mes l("Choose desired quest state:");
+
+ deletearray .@vals;
+ .@menustr$ = menuimage("actions/abort", l("Do nothing")) + ":";
+ .@vals[0] = -0x7FFFFFFF;
+ .@cnt = 1;
+
+ for (.@f = 1; .@f < getargcount(); .@f += 2)
+ {
+ if (getarg(.@f) != "")
+ {
+ .@qv = getarg(.@f + 1);
+ .@s$ = menuimage("actions/" + (.@qv ? "edit" : "reset"), "[" + .@qv + "] " + getarg(.@f));
+ .@menustr$ += (.@qv < 0 ? getarg(.@f) : .@s$) + ":";
+ .@vals[.@cnt] = .@qv;
+ ++.@cnt;
+ }
+ }
+
+ if (is_admin())
+ {
+ .@menustr$ += menuimage("actions/nuke", l("Set state manually"));
+ .@vals[.@cnt] = -0x7FFFFFFE;
+ }
+
+
+ @menu = 255;
+ @menuret = -1;
+ select(.@menustr$);
+ if (@menu == 255)
+ return -1;
+
+ --@menu;
+ if (@menu < 0 || @menu >= getarraysize(.@vals))
+ return -1;
+
+ @menuret = .@vals[@menu];
+
+ switch (@menuret)
+ {
+ case -0x7FFFFFFE: input @menuret; setq getarg(0,0), @menuret;
+ case -0x7FFFFFFF: return 1;
+ }
+
+ if (@menuret >= 0)
+ {
+ setq getarg(0,0), @menuret;
+ }
+ return;
+}
+
+
+
+// selectd
+// like a normal select() but gives access to quest debug
+//
+// quest id can either be passed as first argument
+// or as the .quest_debug npc variable
+
+function script selectd {
+ .@menustr$ = rif(debug, menuaction(l("debug")));
+ .@count = getargcount();
+ .@f = 0;
+ .@questID = getvariableofnpc(.quest_debug, strnpcinfo(0));
+
+ if (.@count > 1 && !isstr(getarg(0)))
+ {
+ ++.@f;
+ .@questID = getarg(0);
+ }
+
+ for (; .@f < .@count; ++.@f)
+ {
+ .@menustr$ += ":" + getarg(.@f);
+ }
+
+ @menu = 255;
+ select .@menustr$;
+
+ switch (@menu)
+ {
+ case -1:
+ case 255: return -1;
+ default: @menu -= 1; return @menu; // FIXME: here I would have done `return --@menu;` but hercules prevents this
+ case 1: callfunc "QuestDebug" + .@questID; closedialog; end;
+ }
+}
diff --git a/npc/functions/questgen.txt b/npc/functions/questgen.txt
new file mode 100644
index 000000000..285924cbd
--- /dev/null
+++ b/npc/functions/questgen.txt
@@ -0,0 +1,38 @@
+// Evol functions.
+// Authors:
+// monwarez
+// Reid
+// Description:
+// Generate a random quest type and location.
+// Variables:
+// @quests : 2D array containing quest type and location availability
+// with @nb_type rows and @nb_location columns.
+// boolean value determine if the connection is possible between
+// the quest type and location selected.
+// @nb_difficulty : difficulty value from 0 to N-1.
+// Argument:
+// 0 : quest type
+// 1 : quest location
+// 2 : quest difficulty
+// Return : Tridimentional array value;
+
+function script questgen {
+
+ .@argc = getargcount();
+ @q_type = getarg(0, rand(@nb_type * 10) / 10);
+
+ do
+ {
+ @q_location = getarg(1, rand(@nb_location * 10) / 10);
+ .@cell = @q_type * @nb_location + @q_location;
+
+ if (!@quests[.@cell] && .@argc >= 2)
+ {
+ return false;
+ }
+ } while (!@quests[.@cell]);
+
+ @q_difficulty = getarg(2, rand(@nb_difficulty * 10) / 10);
+
+ return true;
+}
diff --git a/npc/functions/riddle.txt b/npc/functions/riddle.txt
new file mode 100644
index 000000000..fb503e3b3
--- /dev/null
+++ b/npc/functions/riddle.txt
@@ -0,0 +1,74 @@
+// Evol functions.
+// Author:
+// Reid
+// Description:
+// Riddle enigma validator
+//
+// Arguments
+// 0 PC answer
+// 1 English correct answer
+// 2 Translated correct answer
+
+// TODO: levenshtein(), similar_text(), and maybe even soundex()
+
+function script riddlevalidation {
+ .@answer$ = strtolower(getarg(0));
+ .@good$ = strtolower(getarg(1));
+ .@good_translated$ = strtolower(getarg(2));
+
+ .@size_answer = getstrlen(.@answer$);
+ .@size_good = getstrlen(.@good$);
+ .@size_good_translated = getstrlen(.@good_translated$);
+
+ .@max = max(.@size_answer, .@size_good_translated, .@size_good);
+
+ // Input is too long.
+ if (.@max > 20)
+ {
+ return false;
+ }
+
+ .@size_good *= 70;
+ .@size_good_translated *= 70;
+
+ for (.@i = 0; .@i < .@max; .@i++)
+ {
+ .@correct = 0;
+ .@correct_translated = 0;
+
+ for (.@k = .@k_translated = .@j = .@i; .@j < .@max; .@j++)
+ {
+ if (charat(.@answer$, .@j) == charat(.@good$, .@k))
+ {
+ .@correct++;
+ .@k++;
+ }
+ else
+ {
+ .@correct--;
+ }
+
+ if (charat(.@answer$, .@j) ==
+ charat(.@good_translated$, .@k_translated))
+ {
+ .@correct_translated++;
+ .@k_translated++;
+ }
+ else
+ {
+ .@correct_translated--;
+ }
+ }
+ // if 70% of the word is correct
+ .@correct *= 100;
+ .@correct_translated *= 100;
+
+ if (.@correct >= .@size_good ||
+ .@correct_translated >= .@size_good_translated)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/npc/functions/sailordialogue.txt b/npc/functions/sailordialogue.txt
new file mode 100644
index 000000000..281246f7f
--- /dev/null
+++ b/npc/functions/sailordialogue.txt
@@ -0,0 +1,53 @@
+// Evol functions.
+// Authors:
+// Qwerty Dragon
+// Reid
+// Description:
+// Random sailor dialogues between two categories of NPCs.
+
+function script sailorfood {
+ mesn;
+
+ .@q = rand(0, 400) / 100;
+ if (.@q == 0) goto L_RandomA;
+ if (.@q == 1) goto L_RandomB;
+ if (.@q > 1) goto L_RandomC;
+
+L_RandomA:
+ mesq l("Hey.");
+ next;
+ mesq l("What did Gugli say about the box? Was it ok?");
+ next;
+
+ menu
+ l("It's ok."), L_Fine,
+ l("He needs more food."), -;
+
+ mes "";
+ mesn;
+ mesq l("Oh really? I'll put more food in the next box then.");
+
+ close;
+
+L_Fine:
+ mes "";
+ mesn;
+ mesq l("It's alright! Just one more box and it'll be ok.");
+
+ close;
+
+L_RandomB:
+ mesq l("Thanks for the help!");
+ next;
+ mesq l("These boxes are way too heavy to be lifted by only one person, all the way onto the ship.");
+
+ close;
+
+L_RandomC:
+ mesq l("I think I'll be done soon, since I almost have a box full of @@s!", getitemlink(CrocClaw));
+ next;
+ mesq l("And you? How's it going on your side?");
+ next;
+
+ return;
+}
diff --git a/npc/functions/sailortalk.txt b/npc/functions/sailortalk.txt
new file mode 100644
index 000000000..73145768b
--- /dev/null
+++ b/npc/functions/sailortalk.txt
@@ -0,0 +1,37 @@
+// Evol functions.
+// Author:
+// Reid
+// Description:
+// Tell a random sentence.
+// Variables:
+// .@rand = Random number between the number of sentence choice.
+
+function script sailortalk {
+
+ .@rand = rand(8);
+ if (.@rand == 0) goodbye;
+ if (.@rand == 1)
+ {
+ speech(
+ l("These purple mushrooms are called @@s. There are plenty of 'em on this island!", getitemlink(Plushroom)),
+ l("It's a kind of mushroom that tastes like a marshmallow and looks like a plush! @@, get it?", getitemlink(Plushroom)),
+ l("These funny fungi are mushrooming all around this island. Just pick some @@s and have a try.", getitemlink(Plushroom)));
+ close;
+ }
+ if (.@rand == 2) npctalkonce(l("Good to hear from you!"));
+ if (.@rand == 3) npctalkonce(l("So finally someone has came to visit me?"));
+ if (.@rand == 4)
+ {
+ speech(
+ l("A sunny and hot day,"),
+ l("a quiet place,"),
+ l("a ground!"),
+ l("What else do you need?"));
+ close;
+ }
+ if (.@rand == 5) npctalkonce(l("A-hoy matey!"));
+ if (.@rand == 6) npctalkonce(l("We are glad captain Nard has let you join the crew!"));
+ if (.@rand == 7) npctalkonce(l("Howdy?"));
+
+ end;
+}
diff --git a/npc/functions/savepoint.txt b/npc/functions/savepoint.txt
new file mode 100644
index 000000000..0e0b6f908
--- /dev/null
+++ b/npc/functions/savepoint.txt
@@ -0,0 +1,48 @@
+// Evol functions.
+// Authors:
+// gumi
+// Reid
+// Description:
+// Adds a new save point location.
+// Usage:
+// savepointparticle;
+// savepointparticle NO_INN;
+// savepointparticle map, x, y, NO_INN;
+// Description:
+// Save location with arguments:
+// getarg(0) map name,
+// getarg(1) x's value,
+// getarg(2) y's value,
+// getarg(3) INN flag.
+
+function script savepointparticle {
+
+ if (gettimetick(2) - @lastSave < 5)
+ return;
+
+ .@mapname$ = getarg(0, "");
+ .@mapx = getarg(1, -1);
+ .@mapy = getarg(2, -1);
+ .@i = 3;
+
+ if (.@mapy < 1)
+ {
+ .@npc$ = strnpcinfo(0);
+ .@mapname$ = getvariableofnpc(.map$, .@npc$);
+ .@mapx = getvariableofnpc(.x, .@npc$);
+ .@mapy = getvariableofnpc(.y, .@npc$);
+ .@i = 0;
+ }
+
+ message strcharinfo(0), l("Your position has been saved.");
+
+ if (getarg(.@i, NO_INN) == NO_INN)
+ {
+ INN_REGISTER = NO_INN;
+ }
+ savepoint .@mapname$, .@mapx, .@mapy;
+ specialeffect(4, SELF, getcharid(3));
+ @lastSave = gettimetick(2);
+
+ return;
+}
diff --git a/npc/functions/shops.txt b/npc/functions/shops.txt
new file mode 100644
index 000000000..79890e815
--- /dev/null
+++ b/npc/functions/shops.txt
@@ -0,0 +1,13 @@
+// Evol functions.
+// Author:
+// 4144
+// Description:
+// Shops utility functions
+// Variables:
+// none
+
+function script restoreshopitem {
+ if (shopcount(getarg(0)) < getarg(1))
+ sellitem getarg(0), -1, getarg(1);
+ return;
+}
diff --git a/npc/functions/string.txt b/npc/functions/string.txt
new file mode 100644
index 000000000..efeaf476d
--- /dev/null
+++ b/npc/functions/string.txt
@@ -0,0 +1,195 @@
+// safe string manipulation functions
+// ** does not require PCRE
+
+
+// str(<int>)
+// returns whatever is passed, converted to string
+
+function script str {
+ return "" + getarg(0);
+}
+
+
+
+// startswith("<string>", "<search>")
+// returns true if <string> begins with <search>
+
+function script startswith {
+ return substr(getarg(0), 0, getstrlen(getarg(1)) - 1) == getarg(1);
+}
+
+
+
+// endswith("<string>", "<search>")
+// returns true if <string> ends with <search>
+
+function script endswith {
+ .@t = getstrlen(getarg(0)); // total length
+ .@n = getstrlen(getarg(1)); // substring length
+ return substr(getarg(0), .@t - .@n, .@t - 1) == getarg(1);
+}
+
+
+
+// capitalize("<string>")
+// returns <string> with its first letter capitalized
+
+function script capitalize {
+ return setchar(getarg(0), strtoupper(charat(getarg(0), 0)), 0);
+}
+
+
+
+// titlecase("<string>" {, "<delimiter>" {, <camel>}})
+// returns <string> with the first letter of each word capitalized
+// if <camel> is true, the string is joined in a camelCase fashion
+
+function script titlecase {
+ .@delimiter$ = getarg(1, " ");
+ .@c = getarg(2, 0);
+ explode(.@words$, getarg(0), .@delimiter$);
+
+ for (.@i = (.@c ? 1 : 0); .@i < 255; ++.@i)
+ {
+ if (.@words$[.@i] == "")
+ {
+ break;
+ }
+
+ .@words$[.@i] = setchar(.@words$[.@i], strtoupper(charat(.@words$[.@i], 0)), 0);
+ }
+
+ return implode(.@words$, (.@c ? "" : .@delimiter$));
+}
+
+
+
+// camelcase("<string" {, "<delimiter>"})
+
+function script camelcase {
+ return titlecase(getarg(0), getarg(1, " "), true);
+}
+
+
+
+// zfill("<string>" {, <width> {, "<padding>"}})
+// returns <string> padded to the left with <padding> up to width
+
+function script zfill {
+ .@str$ = getarg(0);
+ .@width = getarg(1, 8);
+ .@padding$ = getarg(2, "0");
+
+ for (.@s = getstrlen(.@str$); .@s < .@width; ++.@s)
+ {
+ .@str$ = .@padding$ + .@str$;
+ }
+
+ return .@str$;
+}
+
+
+
+// format_number(<integer> {, "<separator>"})
+// formats a number properly
+
+function script format_number {
+ .@number$ = str(getarg(0));
+ .@len = getstrlen(.@number$);
+ .@separator$ = getarg(1, ",");
+
+ if (getargcount() < 2 && playerattached()) {
+ // get from user language
+ switch (Lang) {
+ case 1: .@separator$ = " "; break; // French
+ default: .@separator$ = ","; // English (default)
+ }
+ }
+
+ for (.@i = .@len - 3; .@i > 0; .@i -= 3) {
+ .@number$ = insertchar(.@number$, .@separator$, .@i);
+ }
+
+ return .@number$;
+}
+
+
+
+// strip("<string>")
+// removes spaces at the start and end
+
+function script strip {
+ .@s$ = getarg(0);
+ if (.@s$ == "") {
+ return "";
+ }
+ .@start = 0;
+ .@end = getstrlen(.@s$) - 1;
+ for (.@i = .@start; .@i < .@end; .@i++)
+ {
+ if (charat(.@s$, .@i) != " ") {
+ break;
+ } else {
+ .@start++;
+ }
+ }
+ for (.@i = .@end; .@i >= .@start; .@i--)
+ {
+ if (charat(.@s$, .@i) != " ") {
+ break;
+ } else {
+ .@end--;
+ }
+ }
+ return substr(.@s$, .@start, .@end);
+}
+
+
+
+// reverse("<string>")
+// returns <string> reversed
+
+function script reverse {
+ .@str$ = getarg(0);
+ .@len = getstrlen(.@str$);
+
+ for (.@i = 0; .@i < (.@len / 2); ++.@i) {
+ .@tmp$ = charat(.@str$, .@i);
+ .@str$ = setchar(.@str$, charat(.@str$, (.@len - 1 - .@i)), .@i); // a <= b
+ .@str$ = setchar(.@str$, .@tmp$, (.@len - 1 - .@i)); // b <= a
+ }
+
+ return .@str$;
+}
+
+
+
+// repeat("<string>", <multiplier>)
+// repeats <string> many times and returns it
+
+function script repeat {
+ .@mul = getarg(1);
+
+ for (.@i = 0; .@i < .@mul; ++.@i) {
+ .@str$ += getarg(0);
+ }
+
+ return .@str$;
+}
+
+
+
+// shuffle("<string>")
+// returns <string> shuffled
+
+function script shuffle {
+ .@str$ = getarg(0);
+
+ for (.@len = getstrlen(.@str$); .@len > 0; --.@len) {
+ .@rnd = rand(.@len);
+ .@out$ += charat(.@str$, .@rnd);
+ .@str$ = delchar(.@str$, .@rnd);
+ }
+
+ return .@out$;
+}
diff --git a/npc/functions/time.txt b/npc/functions/time.txt
new file mode 100644
index 000000000..30ab9f469
--- /dev/null
+++ b/npc/functions/time.txt
@@ -0,0 +1,108 @@
+function script now {
+ return gettimetick(2);
+}
+
+
+function script time_from_ms {
+ return now() + (getarg(0) / 1000);
+}
+
+function script time_from_seconds {
+ return now() + getarg(0);
+}
+
+function script time_from_minutes {
+ return now() + (getarg(0) * 60);
+}
+
+function script time_from_hours {
+ return now() + (getarg(0) * 3600);
+}
+
+function script time_from_days {
+ return now() + (getarg(0) * 86400);
+}
+
+
+// FuzzyTime(<unix timestamp>{, <options>{, <precision>}})
+// gives time in a human-readable format
+//
+// <options> is bitmasked:
+// 1 do not show "ago" when in past
+// 2 do not show "in" when in the future
+// 4 show "from now" instead of "in" when in the future
+//
+// <precision> is the number of units to show,
+// by default uses max precision
+
+function script FuzzyTime {
+ .@future = getarg(0, now());
+ .@options = getarg(1, 0);
+ .@precision = getarg(2, 99);
+ .@diff = (.@future - now());
+
+ // check if in the past, or in the future
+ if (.@diff < 0) {
+ .@diff *= -1;
+ .@past = true;
+ }
+
+ .@diff = max(1, .@diff);
+
+ if (.@diff >= 31536000) {
+ .@years = (.@diff / 31536000);
+ .@diff = (++.@s == .@precision ? 0 : (.@diff % 31536000));
+ .@ret$ += sprintf("%d %s", .@years, (.@years > 1 ? "years" : "year"));
+ }
+
+ if (.@diff >= 86400) {
+ .@days = (.@diff / 86400);
+ .@diff = (++.@s == .@precision ? 0 : (.@diff % 86400));
+
+ if (.@s > 1) {
+ .@ret$ += (.@diff > 0 ? ", " : " and ");
+ }
+
+ .@ret$ += sprintf("%d %s", .@days, (.@days > 1 ? "days" : "day"));
+ }
+
+ if (.@diff >= 3600) {
+ .@hours = (.@diff / 3600);
+ .@diff = (++.@s == .@precision ? 0 : (.@diff % 3600));
+
+ if (.@s > 1) {
+ .@ret$ += (.@diff > 0 ? ", " : (.@s >= 3 ? ", " : " ") + "and ");
+ }
+
+ .@ret$ += sprintf("%d %s", .@hours, (.@hours > 1 ? "hours" : "hour"));
+ }
+
+ if (.@diff >= 60) {
+ .@minutes = (.@diff / 60);
+ .@diff = (++.@s == .@precision ? 0 : (.@diff % 60));
+
+ if (.@s > 1) {
+ .@ret$ += (.@diff > 0 ? ", " : (.@s >= 3 ? ", " : " ") + "and ");
+ }
+
+ .@ret$ += sprintf("%d %s", .@minutes, (.@minutes > 1 ? "minutes" : "minute"));
+ }
+
+ if (.@diff >= 1) {
+ if (++.@s > 1) {
+ .@ret$ += (.@s >= 3 ? ", " : " ") + "and ";
+ }
+
+ .@ret$ += sprintf("%d %s", .@diff, (.@diff > 1 ? "seconds" : "second"));
+ }
+
+ if (.@past && !(.@options & 1)) {
+ .@ret$ += " ago";
+ }
+
+ if (!(.@past) && !(.@options & 2)) {
+ .@ret$ = ((.@options & 4) ? sprintf("%s from now", .@ret$) : sprintf("in %s", .@ret$));
+ }
+
+ return .@ret$;
+}
diff --git a/npc/functions/timer.txt b/npc/functions/timer.txt
new file mode 100644
index 000000000..e79070f3b
--- /dev/null
+++ b/npc/functions/timer.txt
@@ -0,0 +1,56 @@
+// areatimer("<map>", <x1>, <y1>, <x2>, <y2>, <tick>, "<npc>::<event>")
+function script areatimer {
+ .@c = getunits(BL_PC, .@players, false, getarg(0), getarg(1), getarg(2), getarg(3), getarg(4));
+ for (.@i = 0; .@i < .@c; .@i++) {
+ addtimer(getarg(5), getarg(6), .@players[.@i]);
+ }
+ return .@i;
+}
+
+// areadeltimer("<map>", <x1>, <y1>, <x2>, <y2>, "<npc>::<event>")
+function script areadeltimer {
+ .@c = getunits(BL_PC, .@players, false, getarg(0), getarg(1), getarg(2), getarg(3), getarg(4));
+ for (.@i = 0; .@i < .@c; .@i++) {
+ deltimer(getarg(5), .@players[.@i]);
+ }
+ return .@i;
+}
+
+// areatimer2("<map>", <x1>, <y1>, <x2>, <y2>, <tick>, "<npc>::<event>")
+function script areatimer2 {
+ .@c = getunits(BL_PC, .@players, false, getarg(0), getarg(1), getarg(2), getarg(3), getarg(4));
+ for (.@i = 0; .@i < .@c; .@i++) {
+ deltimer(getarg(6), .@players[.@i]);
+ addtimer(getarg(5), getarg(6), .@players[.@i]);
+ }
+ return .@i;
+}
+
+
+// maptimer("<map>", <tick>, "<npc>::<event>")
+function script maptimer {
+ .@c = getunits(BL_PC, .@players, false, getarg(0));
+ for (.@i = 0; .@i < .@c; .@i++) {
+ addtimer(getarg(1), getarg(2), .@players[.@i]);
+ }
+ return .@i;
+}
+
+// maptimer2("<map>", <tick>, "<npc>::<event>")
+function script maptimer2 {
+ .@c = getunits(BL_PC, .@players, false, getarg(0));
+ for (.@i = 0; .@i < .@c; .@i++) {
+ deltimer(getarg(2), .@players[.@i]);
+ addtimer(getarg(1), getarg(2), .@players[.@i]);
+ }
+ return .@i;
+}
+
+// mapdeltimer("<map>", "<npc>::<event>")
+function script mapdeltimer {
+ .@c = getunits(BL_PC, .@players, false, getarg(0));
+ for (.@i = 0; .@i < .@c; .@i++) {
+ deltimer(getarg(1), .@players[.@i]);
+ }
+ return .@i;
+}
diff --git a/npc/functions/util.txt b/npc/functions/util.txt
new file mode 100644
index 000000000..ae70b233d
--- /dev/null
+++ b/npc/functions/util.txt
@@ -0,0 +1,35 @@
+// Evol functions.
+// Authors:
+// Reid
+// Description:
+// Util functions
+
+
+// season_direction({day, month})
+// returns the direction that represents our current season (approximation)
+// DOWN: Winter, 21/12
+// DOWNLEFT: Spring, 20/03
+// LEFT: Summer, 21/06
+// UPLEFT: Autumn, 22/09
+
+function script season_direction {
+ .@current_month = getarg(0, gettime(GETTIME_MONTH));
+
+ if (.@current_month % 3 == 0)
+ {
+ .@current_day = getarg(1, gettime(GETTIME_DAYOFMONTH));
+
+ switch (.@current_month)
+ {
+ case MARCH: .@season_day = 20; break;
+ case JUNE: .@season_day = 21; break;
+ case SEPTEMBER: .@season_day = 22; break;
+ case DECEMBER: .@season_day = 21; break;
+ default: break;
+ }
+
+ .@is_after_season_day = .@current_day >= .@season_day ? 0 : -1;
+ }
+
+ return (.@current_month / 3 + .@is_after_season_day) % 4;
+}
diff --git a/npc/functions/villagertalk.txt b/npc/functions/villagertalk.txt
new file mode 100644
index 000000000..371a9f20b
--- /dev/null
+++ b/npc/functions/villagertalk.txt
@@ -0,0 +1,53 @@
+// Evol functions.
+// Authors:
+// Akko Teru
+// Qwerty Dragon
+// Reid
+// Description:
+// Tell a random sentence. || There ought to be a law!
+
+function script villagertalk {
+
+ function darn_or_smile
+ {
+ .@darn = rand(42);
+
+ if (.@darn < 26)
+ {
+ emotion E_JOY;
+ hello;
+ }
+ else if (.@darn > 26)
+ {
+ emotion E_LOOKAWAY;
+ goodbye;
+ }
+ else
+ {
+ npctalkonce(l("Stop it!"));
+ }
+
+ return;
+ }
+
+ switch (rand(4))
+ {
+ case 0:
+ darn_or_smile();
+ break;
+ case 1:
+ npctalkonce(l("It is a sunny day, don't you think?"));
+ break;
+ case 2:
+ npctalkonce(l("Go fly a kite."));
+ break;
+ case 3:
+ npctalkonce(l("I just want to live my life in peace."));
+ break;
+ default:
+ emotion E_HAPPY;
+ break;
+ }
+
+ return;
+}
diff --git a/npc/items/croconut.txt b/npc/items/croconut.txt
new file mode 100644
index 000000000..eb8b6d65e
--- /dev/null
+++ b/npc/items/croconut.txt
@@ -0,0 +1,72 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Reid
+// Description:
+// Allows to cut a Croconut in multiple parts.
+//
+// Possible choices for L_Weapon:
+// rif(countitem(35xx), l(getitemname(xx))), L_Weak,
+// rif(countitem(35yy), l(getitemname(yy))), L_Good,
+
+000-2-1,0,0,0 script Croconut NPC_HIDDEN,{
+ close;
+
+OnUse:
+ mesn "Narrator";
+ mes col(l("Do you want to cut this @@?", getitemlink(Croconut)), 9);
+ next;
+
+ menu
+ l("Yes."), L_Weapon,
+ l("No."), -;
+
+ getitem Croconut, 1;
+ close;
+
+L_Weapon:
+ mes "";
+ mesn "Narrator";
+ mes col(l("Which of your weapons do you want to use in order to cut this @@?", getitemlink(Croconut)), 9);
+ next;
+
+ menu
+ rif(countitem(Knife) > 0, l(getitemname(Knife))), L_Weak,
+ rif(countitem(PiouSlayer) > 0, l(getitemname(PiouSlayer))), L_Weak,
+ rif(countitem(TrainingGladius) > 0, l(getitemname(TrainingGladius))), L_Good,
+ rif(countitem(WoodenSword) > 0, l(getitemname(WoodenSword))), L_Weak,
+ rif(countitem(ArtisBacksword) > 0, l(getitemname(ArtisBacksword))), L_Good,
+ l("Bare Hands"), -;
+
+L_TooWeak:
+ mes "";
+ mesn "Narrator";
+
+ .@q = rand(5);
+ if (.@q == 0) goto L_TooWeakLost;
+ if ( (.@q == 1) || (.@q == 2) ) goto L_TooWeakFail;
+ if ( (.@q == 3) || (.@q == 4) || (.@q == 5) ) goto L_Weak;
+
+L_TooWeakLost:
+ mes col(l("You hit too hard with your fist, you destroyed your @@.", getitemlink(Croconut)), 9);
+
+ close;
+
+L_TooWeakFail:
+ mes col(l("Your hands are too weak, you did not succeed in opening this @@.", getitemlink(Croconut)), 9);
+
+ getitem Croconut, 1;
+ close;
+
+L_Weak:
+ mes col(l("You opened the @@ in two parts, but you crushed one of them.", getitemlink(Croconut)), 9);
+
+ getitem HalfCroconut, 1;
+ close;
+
+L_Good:
+ mes col(l("You perfectly cut your @@ into two edible parts.", getitemlink(Croconut)), 9);
+
+ getitem HalfCroconut, 2;
+ close;
+}
diff --git a/npc/items/rand_sc_heal.txt b/npc/items/rand_sc_heal.txt
new file mode 100644
index 000000000..e4b0875a8
--- /dev/null
+++ b/npc/items/rand_sc_heal.txt
@@ -0,0 +1,85 @@
+// Evol scripts.
+// Author:
+// Reid
+// Description:
+// Random heal every x seconds.
+//
+// Variables:
+// @delay Second of healing
+// @min Min amount of healing
+// @max Max amount of healing
+// @type 1 Heal
+// 2 Other
+// 3 Special 1
+// 4 Special 2
+
+- script rand_sc_heal -1,{
+
+ // Add remaning bonus if the last one hasn't finished
+ function remaining_bonus
+ {
+ if (getstatus(getarg(0)))
+ {
+ .@old_val1 = getstatus(getarg(0), 1);
+ .@old_delay = getstatus(getarg(0), 4) * 1000;
+
+ // change the delay to prevent fast healing
+ if (.@old_delay > @delay)
+ {
+ @delay = .@old_delay;
+ @val1 += .@old_val1;
+ }
+ else
+ {
+ @val1 += (.@old_val1 * .@old_delay) / @delay;
+ }
+ }
+ else
+ {
+ @val1 = @val3;
+ }
+ return;
+ }
+
+OnUse:
+ if (@delay <= 0) close;
+
+ // minimum between @min and bVit / 2 * BaseLevel / 10
+ .@vitality_bonus = min(@min, readparam(bVit) * BaseLevel / 20);
+ .@rand_heal_val = rand(@min, @max);
+
+ // val1 is the heal value without the vitality bonus
+ @val1 = .@rand_heal_val / @delay;
+ @val3 = (.@rand_heal_val + .@vitality_bonus) / @delay;
+
+ if (@val1 <= 0) close;
+
+ @delay *= 1000; // Put the delay in ms
+
+ switch (@type)
+ {
+ case 1:
+ .@skill = SC_S_LIFEPOTION;
+ break;
+ case 2:
+ .@skill = SC_L_LIFEPOTION;
+ break;
+ case 3:
+ .@skill = SC_G_LIFEPOTION;
+ break;
+ case 4:
+ .@skill = SC_M_LIFEPOTION;
+ break;
+ default :
+ .@skill = 0;
+ break;
+ }
+ if (.@skill != 0)
+ {
+ remaining_bonus(.@skill);
+ sc_end .@skill;
+ sc_start2 .@skill, @delay, @val1, 1;
+ }
+
+ close;
+}
diff --git a/npc/items/shovel.txt b/npc/items/shovel.txt
new file mode 100644
index 000000000..f01a0fcbe
--- /dev/null
+++ b/npc/items/shovel.txt
@@ -0,0 +1,218 @@
+// Evol scripts.
+// Author:
+// Travolta
+// Description:
+// NPC to use shovel (dig, bury etc)
+
+- script Shovel -1,{
+
+ function CheckDigLocation {
+ getmapxy(.@map$, .@x, .@y, 0);
+ for (.@i = 0; .@i < getarraysize(.WorldDigRect_Map$); .@i++)
+ {
+ if (!strcmp(.WorldDigRect_Map$[.@i], .@map$) &&
+ .WorldDigRect_x1[.@i] <= .@x &&
+ .WorldDigRect_x2[.@i] >= .@x &&
+ .WorldDigRect_y1[.@i] <= .@y &&
+ .WorldDigRect_y2[.@i] >= .@y)
+ {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ function AddDigRect {
+ if (getargcount() < 5)
+ {
+ debugmes "usage: AddDigRect(map$,x1,y1,x2,y2)";
+ return 0;
+ }
+ .@map$ = str(getarg(0));
+ .@x1 = getarg(1);
+ .@y1 = getarg(2);
+ .@x2 = getarg(3);
+ .@y2 = getarg(4);
+ .@size = getarraysize(.WorldDigRect_Map$);
+ .WorldDigRect_Map$[.@size] = .@map$;
+ .WorldDigRect_x1[.@size] = .@x1;
+ .WorldDigRect_y1[.@size] = .@y1;
+ .WorldDigRect_x2[.@size] = .@x2;
+ .WorldDigRect_y2[.@size] = .@y2;
+ return 1;
+ }
+
+ function PlayerIsTired {
+ .@tick = gettimetick(1);
+ .@playertick = .PlayerTiredTime - readparam(bStr);
+ if (@ShovelLastUsed + max(4, .@playertick) > .@tick)
+ {
+ narrator S_FIRST_BLANK_LINE,
+ lg("You are exhausted, you should rest a bit.");
+ return 1;
+ }
+ @ShovelLastUsed = .@tick;
+ return 0;
+ }
+
+ function Dig {
+ getmapxy(.@map$, .@x, .@y, 0);
+ for (.@i = 0; .@i < getarraysize($WorldBuriedTreasures_id); .@i++)
+ {
+ if (!strcmp($WorldBuriedTreasures_map$[.@i], .@map$) &&
+ $WorldBuriedTreasures_x[.@i] == .@x &&
+ $WorldBuriedTreasures_y[.@i] == .@y)
+ {
+ .@id = $WorldBuriedTreasures_id[.@i];
+ .@amount = $WorldBuriedTreasures_amount[.@i];
+ deletearray $WorldBuriedTreasures_id[.@i], 1;
+ deletearray $WorldBuriedTreasures_amount[.@i], 1;
+ deletearray $WorldBuriedTreasures_map$[.@i], 1;
+ deletearray $WorldBuriedTreasures_x[.@i], 1;
+ deletearray $WorldBuriedTreasures_y[.@i], 1;
+ getitem .@id, .@amount;
+ narrator S_FIRST_BLANK_LINE,
+ l("You found something!"),
+ l("It's @@ @@.", .@amount, getitemname(.@id));
+ return 1;
+ }
+ }
+ narrator S_FIRST_BLANK_LINE, l("Sadly, you found nothing but dirt.");
+ return 0;
+ }
+
+ function Bury {
+ narrator S_FIRST_BLANK_LINE | S_LAST_BLANK_LINE, l("What would you like to bury?");
+ .@items$ = "";
+ getinventorylist;
+ for (.@i = 0; .@i < @inventorylist_count; .@i++)
+ {
+ .@items$ = .@items$ + getitemname(@inventorylist_id[.@i]) + ":";
+ debugmes getitemname(@inventorylist_id[.@i]);
+ }
+ .@idx = select(.@items$) - 1;
+ .@id = @inventorylist_id[.@idx];
+ .@amount = 1;
+ if (@inventorylist_amount[.@idx] > 1)
+ {
+ narrator S_FIRST_BLANK_LINE | S_LAST_BLANK_LINE, l("Amount?");
+ input .@amount, 1, @inventorylist_amount[.@idx];
+ }
+
+ getmapxy(.@map$, .@x, .@y, 0);
+ delitem .@id, .@amount;
+ .@wtc = getarraysize($WorldBuriedTreasures_id);
+ $WorldBuriedTreasures_id[.@wtc] = .@id;
+ $WorldBuriedTreasures_amount[.@wtc] = .@amount;
+ $WorldBuriedTreasures_map$[.@wtc] = .@map$;
+ $WorldBuriedTreasures_x[.@wtc] = .@x;
+ $WorldBuriedTreasures_y[.@wtc] = .@y;
+ narrator S_FIRST_BLANK_LINE, l("You buried @@ @@.", .@amount, getitemname(.@id));
+
+ return 0;
+ }
+
+ function ShovelQuests {
+ getmapxy(.@map$, .@x, .@y, 0);
+ for (.@i = 0; .@i < getarraysize(ShovelQuests_func$); .@i++)
+ {
+ if (!strcmp(ShovelQuests_map$[.@i], .@map$) &&
+ ShovelQuests_x[.@i] == .@x &&
+ ShovelQuests_y[.@i] == .@y)
+ {
+ .@func$ = ShovelQuests_func$[.@i];
+ deletearray ShovelQuests_func$[.@i], 1;
+ deletearray ShovelQuests_map$[.@i], 1;
+ deletearray ShovelQuests_x[.@i], 1;
+ deletearray ShovelQuests_y[.@i], 1;
+ callfunc(.@func$);
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+OnUse:
+ if (!CheckDigLocation())
+ {
+ message strcharinfo(0), l("I can't use the shovel here.");
+ close;
+ }
+
+ narrator S_LAST_BLANK_LINE,
+ l("You hold the shovel in your hands."),
+ l("What are you going to do?");
+
+ .@action = select(
+ l("Dig."),
+ l("Bury."),
+ l("Nothing."));
+
+ switch(.@action)
+ {
+ case 1:
+ if (PlayerIsTired())
+ close;
+ if (!ShovelQuests())
+ Dig();
+ break;
+ case 2:
+ if (PlayerIsTired())
+ close;
+ Bury();
+ break;
+ case 3:
+ narrator S_FIRST_BLANK_LINE, l("You hide your shovel.");
+ break;
+ }
+ close;
+
+OnHour00:
+ if (playerattached())
+ @ShovelLastUsed = 0;
+ end;
+
+OnInit:
+ .PlayerTiredTime = 20;
+ AddDigRect("001-1", 172, 26, 200, 48);
+ end;
+
+}
+
+function script shovel_addquest {
+ if (getargcount() < 4)
+ {
+ debugmes "usage: shovel_addquest(map$,x,y,func$)";
+ return 0;
+ }
+ .@map$ = str(getarg(0));
+ .@x = getarg(1);
+ .@y = getarg(2);
+ .@func$ = str(getarg(3));
+ .@size = getarraysize(ShovelQuests_func$);
+ ShovelQuests_func$[.@size] = .@func$;
+ ShovelQuests_map$[.@size] = .@map$;
+ ShovelQuests_x[.@size] = .@x;
+ ShovelQuests_y[.@size] = .@y;
+ return 1;
+}
+
+function script shovel_adddigrect {
+ if (getargcount() < 5)
+ {
+ debugmes "usage: shovel_adddigrect(map$,x1,y1,x2,y2)";
+ return 0;
+ }
+ .@map$ = str(getarg(0));
+ .@x1 = getarg(1);
+ .@y1 = getarg(2);
+ .@x2 = getarg(3);
+ .@y2 = getarg(4);
+ .@size = getarraysize(getvariableofnpc(.WorldDigRect_Map$, strnpcinfo(3)));
+ set getvariableofnpc(.WorldDigRect_Map$[.@size], strnpcinfo(3)), .@map$;
+ set getvariableofnpc(.WorldDigRect_x1[.@size], strnpcinfo(3)), .@x1;
+ set getvariableofnpc(.WorldDigRect_y1[.@size], strnpcinfo(3)), .@y1;
+ set getvariableofnpc(.WorldDigRect_x2[.@size], strnpcinfo(3)), .@x2;
+ set getvariableofnpc(.WorldDigRect_y2[.@size], strnpcinfo(3)), .@y2;
+ return 1;
+}
diff --git a/npc/re/scripts_main.conf b/npc/re/scripts_main.conf
new file mode 100644
index 000000000..8574cb924
--- /dev/null
+++ b/npc/re/scripts_main.conf
@@ -0,0 +1,4 @@
+// Only files that are included here will be read by the server
+npc_global_list: (
+@include "npc/scripts.conf"
+) // npc_global_list
diff --git a/npc/scripts.conf b/npc/scripts.conf
new file mode 100644
index 000000000..83fb0348a
--- /dev/null
+++ b/npc/scripts.conf
@@ -0,0 +1,109 @@
+// This is the main script import file
+
+// Critical functions
+"npc/functions/permissions.txt",
+
+// General-purpose Framework functions
+"npc/functions/array.txt",
+"npc/functions/time.txt",
+"npc/functions/timer.txt",
+"npc/functions/input.txt",
+"npc/functions/string.txt",
+"npc/functions/RNGesus.txt",
+"npc/functions/math.txt",
+
+// Misc functions
+"npc/functions/main.txt",
+"npc/functions/asleep.txt",
+"npc/functions/barber.txt",
+"npc/functions/clientversion.txt",
+"npc/functions/doors.txt",
+"npc/functions/goodbye.txt",
+"npc/functions/hammocks.txt",
+"npc/functions/harbours.txt",
+"npc/functions/hello.txt",
+"npc/functions/inventoryplace.txt",
+"npc/functions/legiontalk.txt",
+"npc/functions/marriage.txt",
+"npc/functions/npcmove.txt",
+"npc/functions/masks.txt",
+"npc/functions/openbook.txt",
+"npc/functions/questgen.txt",
+"npc/functions/sailordialogue.txt",
+"npc/functions/sailortalk.txt",
+"npc/functions/savepoint.txt",
+"npc/functions/beds.txt",
+"npc/functions/shops.txt",
+"npc/functions/villagertalk.txt",
+"npc/functions/npcmovegraph.txt",
+"npc/functions/fishing.txt",
+"npc/functions/mouboofunc.txt",
+"npc/functions/asklanguage.txt",
+"npc/functions/game-rules.txt",
+"npc/functions/riddle.txt",
+"npc/functions/bank.txt",
+"npc/functions/confused-tree-dict.txt",
+"npc/functions/util.txt",
+
+// quest debug
+"npc/functions/quest-debug/functions.txt",
+"npc/functions/quest-debug/000-ShipQuests_Julia.txt",
+"npc/functions/quest-debug/001-ShipQuests_Arpan.txt",
+"npc/functions/quest-debug/002-ShipQuests_Alige.txt",
+"npc/functions/quest-debug/003-ShipQuests_Peter.txt",
+"npc/functions/quest-debug/004-ShipQuests_Nard.txt",
+"npc/functions/quest-debug/005-ShipQuests_Knife.txt",
+"npc/functions/quest-debug/006-ShipQuests_ArpanMoney.txt",
+"npc/functions/quest-debug/007-ShipQuests_Door.txt",
+"npc/functions/quest-debug/009-ShipQuests_TreasureChest.txt",
+"npc/functions/quest-debug/010-ShipQuests_Ale.txt",
+"npc/functions/quest-debug/011-ShipQuests_Astapolos.txt",
+"npc/functions/quest-debug/012-ShipQuests_Gulukan.txt",
+"npc/functions/quest-debug/013-ShipQuests_Jalad.txt",
+"npc/functions/quest-debug/014-ShipQuests_QMuller.txt",
+"npc/functions/quest-debug/015-ShipQuests_Tibbo.txt",
+"npc/functions/quest-debug/016-ShipQuests_Gugli.txt",
+"npc/functions/quest-debug/017-ShipQuests_ChefGado.txt",
+"npc/functions/quest-debug/018-General_Cookies.txt",
+"npc/functions/quest-debug/019-ArtisQuests_LazyBrother.txt",
+"npc/functions/quest-debug/020-ArtisQuests_Urchin.txt",
+"npc/functions/quest-debug/021-ArtisQuests_CatchPiou.txt",
+"npc/functions/quest-debug/022-ArtisQuests_Fishman.txt",
+"npc/functions/quest-debug/023-ArtisQuests_QOnan.txt",
+// 24: quest removed (Halloween_VisitArtis)
+// 25: quest removed (Halloween_BarrelQuest)
+"npc/functions/quest-debug/026-General_Rumly.txt",
+"npc/functions/quest-debug/027-ArtisQuests_Enora.txt",
+"npc/functions/quest-debug/028-General_Narrator.txt",
+"npc/functions/quest-debug/029-ArtisQuests_Fexil.txt",
+"npc/functions/quest-debug/030-ArtisQuests_Lloyd.txt",
+"npc/functions/quest-debug/031-General_Janus.txt",
+"npc/functions/quest-debug/032-ArtisQuests_MonaDad.txt",
+"npc/functions/quest-debug/033-Artis_Legion_Progress.txt",
+
+// Item functions
+"npc/items/croconut.txt",
+"npc/items/shovel.txt",
+"npc/items/rand_sc_heal.txt",
+
+// custom atcommands
+"npc/commands/music.txt",
+"npc/commands/warp.txt",
+"npc/commands/zeny.txt",
+"npc/commands/motd-debug-text.txt",
+"npc/commands/motd.txt",
+"npc/commands/scheduled-broadcasts.txt",
+"npc/commands/rate-management.txt",
+"npc/commands/event.txt",
+"npc/commands/debug-look.txt",
+"npc/commands/debug-quest.txt",
+"npc/commands/debug-skill.txt",
+"npc/commands/debug-preset.txt",
+"npc/commands/debug.txt",
+"npc/commands/super-menu.txt",
+
+// config script
+"npc/config/hairstyle_config.txt",
+
+// Maps specific scripts
+@include "npc/_import.txt"
diff --git a/npc/test/_import.txt b/npc/test/_import.txt
new file mode 100644
index 000000000..6c7f7e713
--- /dev/null
+++ b/npc/test/_import.txt
@@ -0,0 +1,13 @@
+// Map test: test
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/test/_mobs.txt",
+"npc/test/mapflags.txt",
+"npc/test/npc1.txt",
+"npc/test/npc2.txt",
+"npc/test/npc3.txt",
+"npc/test/npc4.txt",
+"npc/test/npc5.txt",
+"npc/test/npc6.txt",
+"npc/test/npcmarriage.txt",
+"npc/test/test1.txt",
+"npc/test/test2.txt",
diff --git a/npc/test/_mobs.txt b/npc/test/_mobs.txt
new file mode 100644
index 000000000..8bab31019
--- /dev/null
+++ b/npc/test/_mobs.txt
@@ -0,0 +1,15 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map test: test mobs
+test,38,12,1,1 monster Piou 1002,1,1000,1000
+test,38,12,1,1 monster Tortuga 1004,1,1000,1000
+test,44,12,1,1 monster Piou 1002,3,1000,1000
+test,48,10,1,1 monster Tortuga 1004,3,1000,1000
+test,48,10,0,0 monster Piou 1002,1,1000,1000
+test,48,10,0,0 monster Ratto 1005,1,1000,1000
+test,54,10,1,1 monster Piou 1002,3,1000,1000
+test,68,9,0,0 monster Piou 1002,3,1000,1000
+test,68,9,0,0 monster Ratto 1005,1,1000,1000
+test,68,9,1,1 monster Tortuga 1004,3,1000,1000
+test,76,10,1,1 monster Piou 1002,3,1000,1000
+test,76,10,1,1 monster Ratto 1005,1,1000,1000
+test,78,4,1,1 monster Ratto 1005,3,1000,1000
diff --git a/npc/test/mapflags.txt b/npc/test/mapflags.txt
new file mode 100644
index 000000000..6f3199ae8
--- /dev/null
+++ b/npc/test/mapflags.txt
@@ -0,0 +1,2 @@
+test mapflag mask 5
+test mapflag town
diff --git a/npc/test/npc1.txt b/npc/test/npc1.txt
new file mode 100644
index 000000000..a9d15958b
--- /dev/null
+++ b/npc/test/npc1.txt
@@ -0,0 +1,670 @@
+// Evol scripts.
+// Author:
+// 4144
+// Description:
+// test npc1
+
+test,10,10,0 script npc1#door NPC_HIDDEN,0,1,{
+OnTouch:
+ warp "test", 20, 20;
+ close;
+OnUnTouch:
+ doevent "npc1::OnUnTouch";
+}
+
+test,10,10,0 script npc1 NPC_TEST1,3,3,{
+ function areatest
+ {
+ mesn;
+ mes "getareausers(\"test\", 7, 7, 13, 13): " + getareausers("test", 7, 7, 13, 13);
+ mes "getareausers(7, 7, 13, 13): " + getareausers(7, 7, 13, 13);
+ mes "getareausers(\"test\"): " + getareausers("test");
+ mes "getareausers(): " + getareausers();
+ mes "getareausers(\"test\", 1): " + getareausers("test", 1);
+ mes "getareausers(1): " + getareausers(1);
+ next;
+ return;
+ }
+
+L_Start:
+ switch (select("show area", "map", "pc", "change npc direction", "quest test", "cart", "items", "chat", "wall", "craft", "hashtable", "instance", "mercenary", "npc"))
+ {
+ case 1:
+ areatest;
+ break;
+ case 2:
+ while(1)
+ {
+ .@mask = getmapmask("test");
+ mes "current mask: " + str(.@mask);
+ switch (select("show sand:show grass:show fog:hide fog:back"))
+ {
+ case 1:
+ addremovemapmask "test", 4, 8;
+ break;
+ case 2:
+ addremovemapmask "test", 8, 4;
+ break;
+ case 3:
+ addmapmask "test", 2;
+ break;
+ case 4:
+ removemapmask "test", 2;
+ break;
+ case 5:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+
+ case 3:
+ while(1)
+ {
+ switch (select("change sex:setmount 0:setmount 1:setmount 2:test command:back"))
+ {
+ case 1:
+ changecharsex;
+ break;
+ case 2:
+ setmount 0;
+ break;
+ case 3:
+ setmount 1;
+ break;
+ case 4:
+ setmount 2;
+ break;
+ case 5:
+ clientcommand "emote 1";
+ break;
+ case 6:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 4:
+ for (.@f = 0; .@f < 9; .@f ++)
+ {
+ mes "" + .@f;
+ .dir = .@f;
+ next;
+ }
+ break;
+ case 5:
+ mes "current";
+ .@val1 = getq(ShipQuests_Gugli);
+ .@val2 = getq2(ShipQuests_Gugli);
+ .@val3 = getq3(ShipQuests_Gugli);
+ .@valTime = getqtime(ShipQuests_Gugli);
+ mes "val1=" + .@val1;
+ mes "val2=" + .@val2;
+ mes "val3=" + .@val3;
+ mes "valTime=" + .@valTime;
+ .@val1 ++;
+ .@val2 ++;
+ .@val3 ++;
+ .@valTime ++;
+ next;
+ mes "test " + str(.@val1) + ", " + str(.@val2) + ", " + str(.@val3) + ", " + str(.@valTime);
+ setq ShipQuests_Gugli, .@val1, .@val2, .@val3, .@valTime;
+ next;
+ .@val1 = getq(ShipQuests_Gugli);
+ .@val2 = getq2(ShipQuests_Gugli);
+ .@val3 = getq3(ShipQuests_Gugli);
+ .@valTime = getqtime(ShipQuests_Gugli);
+ mes "val1=" + .@val1;
+ mes "val2=" + .@val2;
+ mes "val3=" + .@val3;
+ mes "valTime=" + .@valTime;
+ break;
+ case 6:
+ while(1)
+ {
+ switch (select("add cart:remove cart:back"))
+ {
+ case 1:
+ setcart 1;
+ break;
+ case 2:
+ setcart 0;
+ break;
+ case 3:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 7:
+ while(1)
+ {
+ switch (select("refine", "rent", "bound", "named", "cards", "options", "back"))
+ {
+ case 1:
+ .@item = -1;
+ while(1)
+ {
+ switch (select("set item", "refine +1", "refine -1", "refine fail", "back"))
+ {
+ case 1:
+ .@item = requestitemindex();
+ mes "Item index selected: " + str(.@item);
+ break;
+ case 2:
+ successrefindex .@item, 1;
+ break;
+ case 3:
+ downrefindex .@item, 1;
+ break;
+ case 4:
+ failedrefindex .@item;
+ break;
+ case 5:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 2:
+ while(1)
+ {
+ switch (select("rent vneck for 10 seconds",
+ "rent vneck for 30 seconds",
+ "rent vneck for 1 minute",
+ "rent vneck for 5 minutes",
+ "back"))
+ {
+ case 1:
+ rentitem 1301, 10;
+ break;
+ case 2:
+ rentitem 1301, 30;
+ break;
+ case 3:
+ rentitem 1301, 60;
+ break;
+ case 4:
+ rentitem 1301, 300;
+ break;
+ case 5:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 3:
+ while(1)
+ {
+ switch (select("get bound vneck",
+ "back"))
+ {
+ case 1:
+ getitembound2 1301, 1, 1, 0, 0, 0, 0, 0, 0, 1;
+ break;
+ case 2:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 4:
+ while(1)
+ {
+ switch (select("get named vneck",
+ "back"))
+ {
+ case 1:
+ getnameditem 1301, "4144";
+ break;
+ case 2:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 5:
+ .@item = -1;
+ while(1)
+ {
+ switch (select("set item",
+ "remove cards success",
+ "fail, remove both",
+ "fail, remove card",
+ "fail, remove item",
+ "fail, safe",
+ "print all",
+ "remove 0",
+ "back"))
+ {
+ case 1:
+ .@item = requestitemindex();
+ mes "Item index selected: " + str(.@item);
+ break;
+ case 2:
+ successremovecardsindex .@item;
+ break;
+ case 3:
+ failedremovecardsindex .@item, 0;
+ break;
+ case 4:
+ failedremovecardsindex .@item, 1;
+ break;
+ case 5:
+ failedremovecardsindex .@item, 2;
+ break;
+ case 6:
+ failedremovecardsindex .@item, 3;
+ break;
+ case 7:
+ mes "slots=" + str(MAX_SLOTS);
+ for (.@i = 0; .@i < MAX_SLOTS; .@i++)
+ {
+ mes "slot " + str(.@i) + " = " + str(getcardbyindex(.@item, .@i));
+ }
+ mes "item options:";
+ for (.@i = 0; .@i < 5; .@i ++)
+ {
+ mes sprintf("%d: Option: %d, Value: %d", .@i, getitemoptionidbyindex(.@item, .@i), getitemoptionvaluebyindex(.@item, .@i));
+ }
+ break;
+ case 8:
+ removecardbyindex(.@item, 0);
+ break;
+ case 9:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 6:
+ .@item = -1;
+ while(1)
+ {
+ switch (select("set item", "info", "set option 1", "remove options", "back"))
+ {
+ case 1:
+ .@item = requestitemindex();
+ mes "Item index selected: " + str(.@item);
+ break;
+ case 2:
+ mes "Selected item options";
+ for (.@i = 0; .@i < 5; .@i ++)
+ {
+ mes sprintf("%d: Option: %d, Value: %d", .@i, getitemoptionidbyindex(.@item, .@i), getitemoptionvaluebyindex(.@item, .@i));
+ }
+ break;
+ case 3:
+ setitemoptionbyindex(.@item, 0, VAR_MAXHPAMOUNT, 200);
+ setitemoptionbyindex(.@item, 1, VAR_STRAMOUNT, 10);
+ setitemoptionbyindex(.@item, 2, VAR_VITAMOUNT, -5);
+ break;
+ case 4:
+ mes "Remove item options";
+ for (.@i = 0; .@i < 5; .@i ++)
+ {
+ setitemoptionbyindex(.@item, .@i, 0, 0);
+ }
+ break;
+ case 5:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 7:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 8:
+ chatjoin .chat;
+ close;
+ case 9:
+ while(1)
+ {
+ switch (select("set wall 1:set wall 2:set wall 3:delete wall 1:delete wall 2:delete wall 3:back"))
+ {
+ case 1:
+ setcells "test", 14, 11, 17, 11, 3, "wall1";
+ break;
+ case 2:
+ setcells "test", 14, 7, 21, 8, 1, "wall2";
+ break;
+ case 3:
+ setcells "test", 13, 15, 13, 21, 3, "wall3";
+ break;
+ case 4:
+ delcells "wall1";
+ break;
+ case 5:
+ delcells "wall2";
+ break;
+ case 6:
+ delcells "wall3";
+ break;
+ case 7:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 10:
+ while(1)
+ {
+ switch (select("technical:normal:back"))
+ {
+ case 1:
+ setskin "test2";
+ .@var$ = requestcraft(9);
+ mes .@var$;
+ .@craft = initcraft(.@var$);
+ mes "craft id: " + str(.@craft);
+ mes "is craft valid: " + validatecraft(.@craft);
+ .@id = getcraftslotid(.@craft, 0);
+ .@amount = getcraftslotamount(.@craft, 0);
+ mes "first item id: " + .@id;
+ mes "first item name: " + getitemlink(.@id);
+ mes "first item amount: " + .@amount;
+
+ .@id = getcraftslotid(.@craft, 1);
+ .@amount = getcraftslotamount(.@craft, 1);
+ mes "second item id: " + .@id;
+ mes "second item name: " + getitemlink(.@id);
+ mes "second item amount: " + .@amount;
+// dumpcraft .@craft;
+ .@entry = findcraftentry(.@craft, 0);
+ mes "found craft entry: " + .@entry;
+ if (.@entry < 0)
+ {
+ mes "no craft recipe found";
+ }
+ else
+ {
+ mes "use craft";
+ usecraft .@craft;
+ mes "return code: " + getcraftcode(.@entry);
+ }
+ deletecraft .@craft;
+ setskin "";
+ break;
+ case 2:
+ mes "put items what you want to craft";
+ setskin "test2";
+ .@var$ = requestcraft(9);
+ setskin "";
+ .@craft = initcraft(.@var$);
+ if (.@craft < 0)
+ {
+ mes "Craft error.";
+ goto L_Start;
+ }
+ mes "lets see what you can get...";
+ next;
+ if (!validatecraft(.@craft))
+ {
+ mes "inventory was changed.";
+ goto L_Start;
+ }
+ .@entry = findcraftentry(.@craft, 0);
+ if (.@entry < 0)
+ {
+ mes "no craft recipe found";
+ }
+ else
+ {
+ mes "found recipe";
+ usecraft .@craft;
+ mes "return code: " + getcraftcode(.@entry);
+ }
+ deletecraft .@craft;
+ break;
+ case 3:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 11:
+ switch(select("Create new hashtable",
+ "Use existing ID"))
+ {
+ case 1:
+ .@ht = htnew();
+ mes "ID = " + .@ht;
+ break;
+ case 2:
+ mes "Input ID";
+ input .@ht;
+ break;
+ }
+ .@defval = 0;
+ .@defval_str$ = "";
+ .@newval = 0;
+ .@newval_str$ = "";
+ .@key$ = "";
+
+ while(1)
+ {
+ switch (select("Set default string value",
+ "Set default number value",
+ "Get string",
+ "Get number",
+ "Put string",
+ "Put number",
+ "Show hashtable",
+ "Clear hashtable",
+ "Delete hashtable",
+ "Exit"))
+ {
+ case 1:
+ input .@defval_str$;
+ break;
+ case 2:
+ input .@defval;
+ break;
+ case 3:
+ mes "Input key:";
+ input .@key$;
+ mes "htget(" + .@ht + ", \"" + .@key$ + "\") = " + htget(.@ht, .@key$);
+ mes "htget(" + .@ht + ", \"" + .@key$ + "\", \"" + .@defval_str$ + "\") = " + htget(.@ht, .@key$, .@defval_str$);
+ break;
+ case 4:
+ mes "Input key:";
+ input .@key$;
+ mes "htget(" + .@ht + ", \"" + .@key$ + "\") = " + htget(.@ht, .@key$);
+ mes "htget(" + .@ht + ", \"" + .@key$ + "\", " + .@defval + ") = " + htget(.@ht, .@key$, .@defval);
+ break;
+ case 5:
+ mes "Input key:";
+ input .@key$;
+ mes "Input value:";
+ input .@newval_str$;
+ htput(.@ht, .@key$, .@newval_str$);
+ mes "htput(" + .@ht + ", \"" + .@key$ + "\", \"" + .@newval_str$ + "\")";
+ mes "htget(" + .@ht + ", \"" + .@key$ + "\") = " + htget(.@ht, .@key$);
+ break;
+ case 6:
+ mes "Input key:";
+ input .@key$;
+ mes "Input value:";
+ input .@newval;
+ htput(.@ht, .@key$, .@newval);
+ mes "htput(" + .@ht + ", \"" + .@key$ + "\", " + .@newval + ")";
+ mes "htget(" + .@ht + ", \"" + .@key$ + "\") = " + htget(.@ht, .@key$);
+ break;
+ case 7:
+ mes "size = " + htsize(.@ht);
+ .@hti = htiterator(.@ht);
+ for(.@key$ = htinextkey(.@hti); hticheck(.@hti); .@key$ = htinextkey(.@hti))
+ mes "key = " + .@key$ + " value = " + htget(.@ht, .@key$);
+ htidelete(.@hti);
+ break;
+ case 8:
+ htclear(.@ht);
+ mes "htclear(" + .@ht + ")";
+ break;
+ case 9:
+ htdelete(.@ht);
+ mes "htdelete(" + .@ht + ")";
+ break;
+ case 10:
+ goto L_Start;
+ } // switch
+ } // while
+ break;
+ case 12:
+ while(1)
+ {
+ switch (select("create", "warp", "info", "warp back", "delete", "back"))
+ {
+ case 1:
+ if (.instid >= 0)
+ {
+ mes "Error: test instance already created";
+ break;
+ }
+// .instid = instance_create("test@instance", 0, 0);
+ .instid = instance_create("test@instance", getcharid(3), IOT_CHAR);
+ if (.instid < 0)
+ {
+ mes "Error: creating instance";
+ break;
+ }
+ mes "new instance id: " + str(.instid);
+// .@instanceMapName$ = instance_attachmap("test", .instid, 1, "test@map1");
+// .@instanceMapName$ = instance_attachmap("test", .instid, 1);
+ .@instanceMapName$ = instance_attachmap("test", .instid, 0, "test@map1");
+ if (.@instanceMapName$ == "")
+ {
+ mes "Error: instance attach map error";
+ break;
+ }
+ mes "Attached instance map name: " + .@instanceMapName$;
+ instance_set_timeout(1000000, 1000000, .instid);
+ instance_init(.instid);
+ break;
+ case 2:
+ warp "test@map1", 12, 12;
+ break;
+ case 3:
+ mes "npc name: " + .name$;
+ mes "npc ext name: " + .extname$;
+ mes "npc id: " + .id;
+ mes "npc parent id: " + .parent;
+ mes "npc src id: " + .srcId;
+ if (instance_id() >= 0)
+ {
+ mes "npc1 in instance named: " + instance_npcname("npc1");
+ }
+ else
+ {
+ mes "npc1 not in instance";
+ }
+ break;
+ case 4:
+ warp "test", 12, 12;
+ break;
+ case 5:
+ if (.instid < 0)
+ {
+ mes "Error: test instance was not created";
+ break;
+ }
+ instance_destroy(.instid);
+ break;
+ case 6:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 13:
+ while(1)
+ {
+ switch (select("create mercenary for 10 seconds", "create mercenary for 1 min", "create mercenary for 10 min", "back"))
+ {
+ case 1:
+ mercenary_create 1191, 10000;
+ break;
+ case 2:
+ mercenary_create 1191, 60000;
+ break;
+ case 3:
+ mercenary_create 1191, 600000;
+ break;
+ case 4:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ case 14:
+ while(1)
+ {
+ switch (select("set hair 1", "set hair 0", "equip vneck", "unequip vneck", "back"))
+ {
+ case 1:
+ setunitdata(.@npcId, UDT_HAIRSTYLE, 5);
+ setunitdata(.@npcId, UDT_HAIRCOLOR, 17);
+ break;
+ case 2:
+ .@npcId = getnpcid(0, "npc4");
+ setunitdata(.@npcId, UDT_HAIRSTYLE, 0);
+ break;
+ case 3:
+ .@npcId = getnpcid(0, "npc4");
+ setunitdata(.@npcId, UDT_HEADTOP, 1301);
+ break;
+ case 4:
+ .@npcId = getnpcid(0, "npc4");
+ setunitdata(.@npcId, UDT_HEADTOP, 0);
+ break;
+ case 5:
+ goto L_Start;
+ break;
+ }
+ }
+ break;
+ }
+
+ close;
+
+OnTouch:
+ doorTouch;
+
+OnUnTouch:
+ doorUnTouch;
+
+OnTimer340:
+ doorTimer;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 5;
+ .alwaysVisible = true;
+ waitingroom "test room", 2, "npc1::OnReadyCheck", 1;
+ // test instance id
+ .instid = -10;
+ if (.parent != 0)
+ {
+ setnpcdir 0;
+ }
+ end;
+
+OnWhisperGlobal:
+ mes "cmd: " + @whispervar0$;
+ close;
+
+OnSkillInvoke:
+ skillInvoke[@skillId] = skillInvoke[@skillId] + 1;
+ end;
+
+OnReadyCheck:
+ debugmes "OnReadyCheck";
+ $@bgid1 = waitingroom2bg("testbg", 10, 10, "bgnpc1::OnLogout","bgnpc1:OnDie");
+ debugmes "bgid=" + str($@bgid1);
+ setbgteam $@bgid1, 1;
+ bg_warp $@bgid1, "testbg", 10, 10;
+}
diff --git a/npc/test/npc2.txt b/npc/test/npc2.txt
new file mode 100644
index 000000000..8a2146f11
--- /dev/null
+++ b/npc/test/npc2.txt
@@ -0,0 +1,35 @@
+// Evol scripts.
+// Author:
+// 4144
+// Description:
+// test npc2
+
+test,20,10,0 trader npc2 NPC_HAT_BOX,{
+OnInit:
+ tradertype(NST_MARKET);
+ sellitem 505, -1, 10;
+ sellitem 502, -1, 10;
+ sellitem 513, -1, 10;
+ sellitem 509, -1, 10;
+ sellitem 2000, -1, 10;
+ sellitem 1800, -1, 10;
+ sellitem 3501, -1, 10;
+ end;
+
+OnClock0000:
+ if (shopcount(505) < 10)
+ sellitem 505, -1, 10;
+ if (shopcount(502) < 10)
+ sellitem 502, -1, 10;
+ if (shopcount(513) < 10)
+ sellitem 513, -1, 10;
+ if (shopcount(509) < 10)
+ sellitem 509, -1, 10;
+ if (shopcount(2000) < 10)
+ sellitem 2000, -1, 10;
+ if (shopcount(1800) < 10)
+ sellitem 1800, -1, 10;
+ if (shopcount(3501) < 10)
+ sellitem 3501, -1, 10;
+ end;
+}
diff --git a/npc/test/npc3.txt b/npc/test/npc3.txt
new file mode 100644
index 000000000..82d5fe3f3
--- /dev/null
+++ b/npc/test/npc3.txt
@@ -0,0 +1,7 @@
+// Evol scripts.
+// Author:
+// 4144
+// Description:
+// test npc3
+
+test,25,10,0 cashshop npc3 NPC_SHOP_BAG,505:100,502:-1,513:-1,509:-1,2000:-1,1800:-1,3501:-1
diff --git a/npc/test/npc4.txt b/npc/test/npc4.txt
new file mode 100644
index 000000000..b85d1bf88
--- /dev/null
+++ b/npc/test/npc4.txt
@@ -0,0 +1,30 @@
+// Evol scripts.
+// Author:
+// 4144
+// Description:
+// test npc4
+
+test,25,20,0 script npc4 NPC_PLAYER,{
+ close;
+OnTimer1000:
+ domovestep;
+OnInit:
+ .walkmask = WALK_WATER;
+ initpath "move", 20, 20,
+ "sit", 0, 0,
+ "dir", 6, 0,
+ "move", 25, 20,
+ "emote", 3, 0,
+// "class", 104, 0,
+ "speed", 100, 0,
+ "wait", 2, 0,
+ "move", 22, 10,
+ "rmove", 3, 3,
+// "class", 801, 0,
+ "speed", 200, 0,
+ "wait", 1, 0,
+ "warp", 22, 30,
+ "goto", 0, 0;
+ initialmove;
+ initnpctimer;
+}
diff --git a/npc/test/npc5.txt b/npc/test/npc5.txt
new file mode 100644
index 000000000..faa655e8f
--- /dev/null
+++ b/npc/test/npc5.txt
@@ -0,0 +1,34 @@
+// Evol scripts.
+// Author:
+// Travolta
+// Description:
+// test npc5
+
+function script npc5TestFunc {
+ npctalk getarg(0);
+ return 0;
+}
+
+test,45,25,0 script npc5 NPC_PLAYER,{
+ close;
+
+OnTimer1000:
+ dographmovestep;
+
+OnInit:
+ // .debug = 1;
+ initmovegraph "topleft", 45, 25,
+ "topright", 55, 25,
+ "bottomright", 55, 34,
+ "bottomleft", 45, 34;
+
+ setmovegraphcmd "topleft", "topright", 30, "dir 0; wait 1",
+ "topleft", "bottomright", 20, "class 104",
+ "topleft", "bottomleft", 50, "emote 8; wait 1; warp bottomright",
+ "topright", "bottomleft", 1, "emote 3; wait 5",
+ "bottomleft", "topleft", 25, "dir 2; wait 1; call npc5TestFunc Hello=)",
+ "bottomleft", "bottomright", 10, "speed 40",
+ "bottomright", "bottomleft", 1, "class 801; speed 100; dir 0; emote 1; wait 4";
+ firstmove "wait 1; speed 100; dir 4; emote 7";
+ initnpctimer;
+}
diff --git a/npc/test/npc6.txt b/npc/test/npc6.txt
new file mode 100644
index 000000000..7c4893ad7
--- /dev/null
+++ b/npc/test/npc6.txt
@@ -0,0 +1,23 @@
+// Evol scripts.
+// Authors:
+// 4144
+// Description:
+// test npc1
+
+test,30,10,0 trader npc6 NPC_SHOP_BAG_TEST,{
+ end;
+
+OnCountFunds:
+ setcurrency 10000;
+ end;
+
+OnPayFunds:
+ dispbottom "Hi: price="+@price+" and points="+@points;
+ // check and remove points
+ purchaseok;
+ end;
+OnInit:
+ tradertype NST_CUSTOM;
+ sellitem Acorn, 500;
+ sellitem Bread, 200;
+}
diff --git a/npc/test/npcmarriage.txt b/npc/test/npcmarriage.txt
new file mode 100644
index 000000000..1b7497bdc
--- /dev/null
+++ b/npc/test/npcmarriage.txt
@@ -0,0 +1,19 @@
+// Evol scripts.
+// Author:
+// 4144
+// Description:
+// npc marriage
+
+test,25,14,0 script marriage1 NPC_PLAYER,{
+ marriagemain();
+ close;
+
+OnTimer30000:
+ marriagecheck();
+ end;
+
+OnInit:
+ .sex = G_MALE;
+ .distance = 3;
+ initnpctimer;
+}
diff --git a/npc/test/test1.txt b/npc/test/test1.txt
new file mode 100644
index 000000000..a6e6d4b94
--- /dev/null
+++ b/npc/test/test1.txt
@@ -0,0 +1,76 @@
+// Evol scripts.
+// Author:
+// 4144
+// Description:
+// script tests
+
+function script test1function {
+ .var = .walkmask;
+ if (.var != 3)
+ mes "Error: testing test1 npc variables from function.";
+ .var = getvariableofnpc(.walkmask, "test1");
+ if (.var != 3)
+ mes "Error: testing test1 npc variables from function.";
+ .var = getvariableofnpc(.walkmask, "test2");
+ if (.var != 4)
+ mes "Error: testing test2 npc variables from function.";
+
+ return;
+}
+
+test,10,5,0 script test1 NPC_HAT_BOX,{
+ mes "Npc vars testing...";
+ .var = .walkmask;
+ if (.var != 3)
+ mes "Error: testing test1 npc variables.";
+ .var = getvariableofnpc(.walkmask, "test1");
+ if (.var != 3)
+ mes "Error: testing test1 npc variables from function.";
+ .var = getvariableofnpc(.walkmask, "test2");
+ if (.var != 4)
+ mes "Error: testing test2 npc variables.";
+ test1function;
+ mes "Formatting testing...";
+ if (l("test @@", "") != "test ")
+ mes "Error: format string 'l(\"test @@\", \"\")': " + l("test @@", "");
+ if (l("test @@", "1") != "test 1")
+ mes "Error: format string 'l(\"test @@\", \"1\")': " + l("test @@", "1");
+ if (l("@@", "") != "")
+ mes "Error: format string 'l(\"@@\", \"\")': " + l("@@", "");
+ if (l("@@") != "@@")
+ mes "Error: format string 'l(\"@@\")': " + l("@@");
+ if (l("@@ @@ @@", "this", "is", "test") != "this is test")
+ mes "Error: format string 'l(\"@@ @@ @@\", \"this\", \"is\", \"test\") != \"this is test\"': " + l("@@ @@ @@", "this", "is", "test");
+ if (l("data @@ @@ @@ data", "this", "is", "test") != "data this is test data")
+ mes "Error: format string 'l(\"data @@ @@ @@ data\", \"this\", \"is\", \"test\")': " + l("data @@ @@ @@ data", "this", "is", "test");
+ mes "Quest vars testing...";
+ .@time = 1000;
+ setq Test_testing1, 1, 2, 3, .@time;
+ if (getq(Test_testing1) != 1)
+ mes "Error: quest variable 1 error. Must be 1, but get " + str(getq(Test_testing1));
+ if (getq2(Test_testing1) != 2)
+ mes "Error: quest variable 2 error. Must be 2, but get " + str(getq(Test_testing1));
+ if (getq3(Test_testing1) != 3)
+ mes "Error: quest variable 3 error. Must be 3, but get " + str(getq(Test_testing1));
+ if (getqtime(Test_testing1) != .@time)
+ mes "Error: quest variable 3 error. Must be 3, but get " + str(getqtime(Test_testing1));
+ next;
+ .@time = 2000;
+ setq Test_testing1, 2, 3, 4, .@time;
+ if (getq(Test_testing1) != 2)
+ mes "Error: quest variable 1 error. Must be 2, but get " + str(getq(Test_testing1));
+ if (getq2(Test_testing1) != 3)
+ mes "Error: quest variable 2 error. Must be 3, but get " + str(getq(Test_testing1));
+ if (getq3(Test_testing1) != 4)
+ mes "Error: quest variable 3 error. Must be 4, but get " + str(getq(Test_testing1));
+ if (getqtime(Test_testing1) != .@time)
+ mes "Error: quest variable 3 error. Must be 3, but get " + str(getqtime(Test_testing1));
+ next;
+ setq Test_testing1, 0;
+ mes "Tests complete.";
+ close;
+
+OnInit:
+ .walkmask = 3;
+ end;
+}
diff --git a/npc/test/test2.txt b/npc/test/test2.txt
new file mode 100644
index 000000000..6870463c7
--- /dev/null
+++ b/npc/test/test2.txt
@@ -0,0 +1,13 @@
+// Evol scripts.
+// Author:
+// 4144
+// Description:
+// script tests
+
+test,12,5,0 script test2 NPC_HAT_BOX,{
+ close;
+
+OnInit:
+ .walkmask = 4;
+ end;
+}
diff --git a/npc/testbg/_import.txt b/npc/testbg/_import.txt
new file mode 100644
index 000000000..c8affdf49
--- /dev/null
+++ b/npc/testbg/_import.txt
@@ -0,0 +1,3 @@
+// Map testbg: testbg
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/testbg/mapflags.txt",
diff --git a/npc/testbg/mapflags.txt b/npc/testbg/mapflags.txt
new file mode 100644
index 000000000..764a55dfe
--- /dev/null
+++ b/npc/testbg/mapflags.txt
@@ -0,0 +1 @@
+testbg mapflag battleground