Author Topic: Explore the world of Alefgard! and talk to some people!  (Read 5984 times)

0 Members and 1 Guest are viewing this topic.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Explore the world of Alefgard! and talk to some people!
« on: October 16, 2019, 07:40:12 pm »
You can move all about the map, enter Towns, the Castle, and Caves(which are all lit at this time) to enter caves or use stairs press SpaceBar, select STAIRS then press SpaceBar again. Enter will cancel the Command window. There is an option to see the controls, but they are not customize-able while running yet. Just hit ESC to quit(after startup menu). The message handler is a bit buggy right now,  But for the most part it works to this point, and you can enjoy the 8 bit style background music and sound effects(bump into a wall ,stairs)!
Tested on 1.3 build from 4/2019, working.
Be sure to download the MFI(Multi-File Index) resource file from below. Easier than having to download over a dozen or so files.

Code: QB64: [Select]
  1. TYPE Player
  2.  Nam AS STRING * 8 '24 'eventually
  3.  Max_HP AS _UNSIGNED _BYTE
  4.  Max_MP AS _UNSIGNED _BYTE
  5.  Pack AS STRING * 32 '_MEM
  6.  Items AS _BYTE 'items in pack
  7.  Armor AS _BYTE
  8.  Weapon AS _BYTE
  9.  Shield AS _BYTE
  10.  Age AS _BYTE 'as player gains experiance levels they age, age negativliy affects stats.
  11.  Strength AS _BYTE
  12.  Agility AS _BYTE
  13.  Luck AS _BYTE
  14.  Level AS _BYTE
  15.  Spells AS INTEGER
  16.  WorldX AS _BYTE 'players location in over world
  17.  WorldY AS _BYTE
  18.  MapX AS _BYTE 'players location in a castle\town or cave\temple
  19.  MapY AS _BYTE
  20.  Map AS _BYTE 'where is player? -1 to 27 (-1 = over world map)
  21.  Facing AS _BYTE
  22.  Has_Princess AS _BYTE 'is player carring Princess?
  23.  
  24. TYPE Monsters
  25.  Nam AS STRING * 16
  26.  Strength AS _UNSIGNED _BYTE
  27.  Agility AS _UNSIGNED _BYTE
  28.  Max_Hp AS _UNSIGNED _BYTE
  29.  Max_Mp AS _UNSIGNED _BYTE
  30.  SlpResist AS _UNSIGNED _BYTE
  31.  StpSplResist AS _UNSIGNED _BYTE
  32.  HurtResist AS _UNSIGNED _BYTE
  33.  Evasion AS _UNSIGNED _BYTE
  34.  Attk1 AS _BYTE 'special attack 1 - these are additional options to normal physical attack
  35.  Attk1Prob AS _UNSIGNED _BYTE
  36.  Attk2 AS _BYTE 'special attack 2
  37.  Attk2Prob AS _UNSIGNED _BYTE
  38.  Group AS _BYTE
  39.  
  40. TYPE Items
  41.  Nam AS STRING * 16
  42.  Valu AS INTEGER
  43.  Power AS _BYTE
  44.  
  45. TYPE Tiles
  46.  Sprite_ID AS _BYTE 'sprite used on tile
  47.  Is_Town AS _BYTE 'Town ID/Castle ID
  48.  Is_Cave AS _BYTE 'Cave ID
  49.  Is_Stairs AS _BYTE 'Stairs ID
  50.  Territory AS _BYTE 'Monster selection ID, determines which monster are picked for battle
  51.  Encounter_rate AS _UNSIGNED _BYTE 'odds of engaging a monster
  52.  Has_Special AS _BYTE 'does search find something here or is special battle here
  53.  
  54. TYPE Tiles_B
  55.  Sprite_ID AS _BYTE 'sprite used on tile
  56.  Is_Stairs AS _BYTE 'Where Stairs lead(ID)
  57.  Territory AS _BYTE 'Monster selection ID, determines which monster are picked for battle
  58.  Is_Exit AS _BYTE 'does tile lead out of castle or town
  59.  Encounter_rate AS _UNSIGNED _BYTE 'odds of engaging a monster
  60.  Has_Special AS _BYTE 'does search find something here or is special battle here
  61.  
  62. TYPE Place_Data
  63.  Start_X AS _BYTE 'when Entering where do you start.
  64.  Start_Y AS _BYTE '
  65.  Is_Lit AS _BYTE 'is a Torch or Radiant needed to see?
  66.  
  67. TYPE Stair_Data
  68.  Map AS _BYTE 'where is the stairs
  69.  X AS _BYTE 'stairs position
  70.  Y AS _BYTE
  71.  Direction AS _BYTE 'going up or down
  72.  Link AS _BYTE 'links to which other stairs
  73.  
  74. TYPE Treasure_Chest
  75.  Map AS _BYTE
  76.  X AS _BYTE
  77.  Y AS _BYTE
  78.  Treasure AS _BYTE
  79.  Count AS INTEGER
  80.  
  81. TYPE Non_Playable_Character
  82.  Sprite_ID AS _BYTE
  83.  X AS _BYTE 'NPCs location
  84.  Y AS _BYTE
  85.  Map AS _BYTE 'Which town\castle\cave do they live in
  86.  Facing AS _BYTE
  87.  Lines AS _BYTE 'What lines do they say
  88.  Flags AS _BYTE 'used if they change what they say over time
  89.  Can_Move AS _BYTE
  90.  Moving AS _BYTE
  91.  MX AS _BYTE
  92.  MY AS _BYTE
  93.  
  94. TYPE GameData
  95.  Y AS _BYTE
  96.  X AS _BYTE
  97.  Flag AS _BYTE
  98.  JustLeft AS _BYTE 'if player just left town\castle don't reprocess location
  99.  In_Place AS _BYTE 'player is in a town\castle
  100.  LastMove AS LONG 'timer, if player doesn't press any keys his current stats display
  101.  Menu AS _BYTE 'does player have the menu up?
  102.  Selection AS _BYTE 'what selection did player make from menu
  103.  Message AS INTEGER 'current message
  104.  Input_Wait AS _BYTE 'waiting for player input, after message display
  105.  Action AS _BYTE 'what action is player currently performing?(talk,search,stair,take,door,spell,item)
  106.  Lite_Level AS _BYTE 'how much light is there 0-none, 1-torch 2&3-Radiant
  107.  Display_Status AS _BYTE
  108.  Talk_To AS _BYTE 'who is the player talking to?
  109.  Current_BGM AS _BYTE 'which music is currently in background
  110.  YES_NO_Input AS _BYTE
  111.  
  112. TYPE Cords
  113.  X AS _BYTE
  114.  Y AS _BYTE
  115.  
  116. TYPE Flags
  117.  Has_Left_Throne_Room AS _BYTE 'set when Player first leave thrown room after starting game.
  118.  Just_Started AS _BYTE 'Set when player first starts game
  119.  Message_Displaying AS _BYTE
  120.  
  121. CONST TRUE = -1, FALSE = NOT TRUE
  122. CONST DOWN = 0, LEFT = 1, UP = 2, RIGHT = 3
  123. CONST Key_Right = 19712, Key_Left = 19200, Key_Up = 18432, Key_Down = 20480
  124. CONST A_Button = 32, B_Button = 13, Start_Button = 65, Select_Button = 66
  125. CONST MoveDown = 1, MoveLeft = 2, MoveUp = 3, MoveRight = 4
  126. CONST Talking = 1, Stairs = 2, Searching = 3, Spells = 4, Items = 5, Doors = 6, Taking = 7
  127.  
  128. DIM SHARED P(3) AS Player, G AS GameData, F AS Flags
  129. DIM SHARED I(127) AS Items
  130. DIM SHARED M(64) AS Monsters, GF(5) AS SINGLE
  131. DIM SHARED World(127, 127) AS Tiles
  132. DIM SHARED Place(27, 45, 45) AS Tiles_B, PD(-1 TO 27) AS Place_Data, Stairs(127) AS Stair_Data
  133. DIM SHARED Chest(127) AS Treasure_Chest, NPC(127) AS Non_Playable_Character, Script(360) AS STRING
  134. DIM SHARED Lines(127, 8, 8) AS INTEGER 'dialog for NPCs
  135. DIM SHARED SA(10) AS Cords, Frames%
  136. DIM SHARED Layer(32) AS LONG, DWFont AS LONG, Frame%%, SFX(32) AS LONG, BGM(-1 TO 27) AS LONG
  137. DIM SHARED ClearLayerMaster AS _MEM
  138.  
  139. ON TIMER(T&, .25) Frame_Change
  140. ON TIMER(T1&, 1) FPS
  141.  
  142. MFI_Loader "DragonW.MFI"
  143. 'selection arrows for command window
  144. DATA 13,4,13,6,13,8,13,10,21,4,21,6,21,8,21,10,0,0,0,0
  145. FOR i%% = 1 TO 10
  146.  READ SA(i%%).X, SA(i%%).Y
  147. NEXT i%%
  148. '-----------------------------------
  149. Layer(0) = _DISPLAY
  150. Layer(1) = _NEWIMAGE(640, 480, 32)
  151. Layer(2) = _NEWIMAGE(255 * 32, 255 * 32, 32) 'world map
  152. 'Layer(3) = _LOADIMAGE("tilebase2.bmp", 32)
  153. 'Layer(4) = _LOADIMAGE("characters.bmp", 32)
  154. Layer(5) = _NEWIMAGE(640, 480, 32)
  155. Layer(6) = _NEWIMAGE(640, 128, 32) 'temp layer to scroll text
  156. Layer(7) = _NEWIMAGE(46 * 32, 46 * 32, 32) 'map layer
  157. Layer(8) = _NEWIMAGE(46 * 32, 46 * 32, 32) 'NPC sprite layer
  158. Layer(9) = _NEWIMAGE(640, 480, 32) 'debug info layer
  159. 'Layer(10) = _LOADIMAGE("controller.bmp", 32)
  160. Layer(11) = _NEWIMAGE(640, 480, 32) 'light mask for underground
  161. Layer(12) = _NEWIMAGE(46 * 32, 46 * 32, 32) 'NPC sprite Clear layer
  162.  
  163. 'DWFont = _LOADFONT("DW1.ttf", 16, "Monospace")
  164. _CLEARCOLOR _RGB32(0, 128, 128), Layer(4)
  165. _CLEARCOLOR _RGB32(0, 0, 0), Layer(12)
  166. ClearLayerMaster = _MEMIMAGE(Layer(12))
  167.  
  168. _FONT DWFont, Layer(1)
  169. _FONT DWFont, Layer(5)
  170.  
  171. LOCATE 1, 1: PRINT "Make a Choice"
  172. PRINT "1- See Controls"
  173. PRINT "2- Explore world"
  174. R% = _KEYHIT
  175. IF R% = 49 THEN CLS: _KEYCLEAR: Control_setup: SLEEP: CLS
  176. LOOP UNTIL R% = 50
  177. PRINT "Building world..."
  178.  
  179. Init_Player 0
  180. P(0).Nam = "Newton"
  181. Build_World_Layer Layer(2)
  182. Build_Place_Layer Layer(7), P(0).Map
  183.  
  184.  
  185. TIMER(T&) ON
  186. who%% = 0
  187. 'G.Input_Wait = TRUE
  188. 'F.Just_Started = TRUE
  189.  
  190. G.LastMove = INT(TIMER + .49)
  191. BGM(13) = BGM(3)
  192. BGM(5) = BGM(3)
  193. BGM(20) = BGM(3)
  194. BGM(25) = BGM(3)
  195. _SNDVOL BGM(-1), .09
  196. _SNDVOL BGM(0), .09
  197. _SNDVOL BGM(1), .09
  198. _SNDVOL BGM(3), .09
  199. '_SNDVOL BGM(13), .09
  200. _SNDVOL SFX(0), .33
  201. _SNDVOL SFX(1), .33
  202. _SNDVOL SFX(2), .33
  203. _SNDVOL SFX(3), .33
  204. Change_BGM 0
  205. TIMER(T1&) ON
  206.  
  207.  IF P(0).Map >= 0 THEN L%% = 7: PMX%% = P(0).MapX: PMY%% = P(0).MapY ELSE L%% = 2: PMX%% = P(0).WorldX: PMY%% = P(0).WorldY
  208.  
  209.  IF NOT F.Message_Displaying THEN Result%% = Controls(0)
  210.  IF Result%% = TRUE THEN ExitFlag%% = TRUE
  211.  IF G.Flag THEN Move_Cycle 0
  212.  
  213.  Copy_Map_Layer Layer(L%%), PMX%% + WX%%, PMY%% + WY%%
  214.  Draw_NPC_Sprites 0, 117, Layer(8)
  215.  
  216.  Copy_NPC_Layer Layer(8), PMX%% + WX%%, PMY%% + WY%%
  217.  
  218.  Draw_Player_Sprite 0, Layer(1)
  219.  
  220.  IF INT(TIMER) > G.LastMove + 1 THEN Draw_Stat_Window Layer(1), 0
  221.  IF G.Menu THEN Draw_Command_Window Layer(1)
  222.  IF G.Message THEN Draw_Info_Window Layer(1): Message_Handler Layer(5), ""
  223.  IF G.Display_Status THEN Display_Player_Status Layer(5)
  224.  ' IF G.Action = Talking THEN TalktoNPC G.Talk_To
  225.  
  226.  Debuginfo
  227.  
  228.  _PUTIMAGE , Layer(5), Layer(1)
  229.  _PUTIMAGE , Layer(9), Layer(1)
  230.  _PUTIMAGE , Layer(1), Layer(0)
  231.  '_DELAY .124
  232.  Process_NPC
  233.  _LIMIT 60
  234.  Frames% = Frames% + 1
  235. LOOP UNTIL ExitFlag%% 'INKEY$ = CHR$(27)
  236.  
  237. TIMER(T1&) OFF
  238.  
  239. _SNDSTOP BGM(G.Current_BGM)
  240.  
  241. SUB FPS
  242.  G.f = Frames%
  243.  Frames% = 0
  244.  
  245. SUB Process_NPC
  246.  FOR i%% = 0 TO 120
  247.   IF NPC(i%%).Can_Move THEN 'only move NPC that are not stationary
  248.    IF NPC(i%%).Moving THEN NPC_Move_Cycle i%%
  249.  
  250.    IF Chance > 250 AND NPC(i%%).Moving = 0 THEN 'start the NPC moving
  251.     SELECT CASE NPC(i%%).Facing 'make sure NPC can move that direction
  252.      CASE UP
  253.       Blocked%% = NPC_Collision(i%%, 0, -1)
  254.      CASE DOWN
  255.       Blocked%% = NPC_Collision(i%%, 0, 1)
  256.      CASE LEFT
  257.       Blocked%% = NPC_Collision(i%%, -1, 0)
  258.      CASE RIGHT
  259.       Blocked%% = NPC_Collision(i%%, 1, 0)
  260.     END SELECT
  261.     IF NOT Blocked%% THEN NPC_Move_Cycle i%%
  262.    END IF
  263.  
  264.    IF Chance < 3 AND NPC(i%%).Moving = 0 THEN Turn_NPC i%%
  265.   END IF
  266.   IF NPC(i%%).X = 0 THEN i%% = 122 'reached the end of NPC list
  267.  NEXT i%%
  268.  
  269. SUB NPC_Move_Cycle (who%%)
  270.  NPC(who%%).Moving = NPC(who%%).Moving + 2
  271.  IF NPC(who%%).Moving = 32 THEN Move_NPC who%%: NPC(who%%).Moving = 0
  272.  SELECT CASE NPC(who%%).Facing
  273.   CASE UP
  274.    NPC(who%%).MY = -NPC(who%%).Moving
  275.   CASE RIGHT
  276.    NPC(who%%).MX = NPC(who%%).Moving
  277.   CASE LEFT
  278.    NPC(who%%).MX = -NPC(who%%).Moving
  279.   CASE DOWN
  280.    NPC(who%%).MY = NPC(who%%).Moving
  281.  
  282. SUB Move_NPC (who%%)
  283.  SELECT CASE NPC(who%%).Facing
  284.   CASE UP
  285.    NPC(who%%).Y = NPC(who%%).Y - 1
  286.   CASE DOWN
  287.    NPC(who%%).Y = NPC(who%%).Y + 1
  288.   CASE LEFT
  289.    NPC(who%%).X = NPC(who%%).X - 1
  290.   CASE RIGHT
  291.    NPC(who%%).X = NPC(who%%).X + 1
  292.  
  293. SUB Turn_NPC (who%%)
  294.  T~%% = Chance
  295.  SELECT CASE T~%%
  296.   CASE 0 TO 63
  297.    NPC(who%%).Facing = UP
  298.   CASE 64 TO 127
  299.    NPC(who%%).Facing = DOWN
  300.   CASE 128 TO 191
  301.    NPC(who%%).Facing = LEFT
  302.   CASE 192 TO 255
  303.    NPC(who%%).Facing = RIGHT
  304.  
  305. FUNCTION NPC_Collision%% (Who%%, X%%, Y%%)
  306.  Result%% = TRUE
  307.  SELECT CASE Place(NPC(Who%%).Map, NPC(Who%%).X + X%%, NPC(Who%%).Y + Y%%).Sprite_ID
  308.   CASE 0 TO 13
  309.    Result%% = FALSE
  310.  'dont let NPC leave map
  311.  IF Place(NPC(Who%%).Map, NPC(Who%%).X + X%%, NPC(Who%%).Y + Y%%).Is_Exit THEN Result%% = TRUE
  312.  IF NOT Result%% THEN 'check for NPC collision
  313.   FOR i%% = 0 TO 120 '<--update when actual NPC count is known
  314.    IF NPC(Who%%).X + X%% = NPC(i%%).X AND NPC(Who%%).Y + Y%% = NPC(i%%).Y AND NPC(Who%%).Map = NPC(i%%).Map THEN
  315.     Result%% = TRUE: i%% = 122
  316.    END IF
  317.    IF NPC(i%%).X = 0 THEN i%% = 122 'no NPC can occupy a 0 location so we know we are past the last NPC
  318.   NEXT i%%
  319.  
  320.  IF NOT Result%% THEN 'check for collision with player
  321.   IF NPC(Who%%).X + X%% = P(0).MapX AND NPC(Who%%).Y + Y%% = P(0).MapY AND NPC(Who%%).Map = P(0).Map THEN Result%% = TRUE
  322.  
  323.  NPC_Collision = Result%%
  324.  
  325.  
  326.  
  327. SUB Process_Command
  328.  SELECT CASE G.Selection
  329.   CASE 1 'talk
  330.    Run_Talk
  331.   CASE 2 'Status
  332.    Run_Status
  333.   CASE 3 'Stairs
  334.    Run_Stairs
  335.   CASE 4 'search
  336.    Run_search
  337.   CASE 5 'spell
  338.    Run_Spell
  339.   CASE 6 'Items
  340.    Run_Item
  341.   CASE 7 'Door
  342.    Run_Door
  343.   CASE 8 'take(chest)
  344.    Run_Take
  345.  
  346. SUB Run_Talk
  347.  Who%% = Find_NPC(P(0).Facing)
  348.  IF Who%% = -1 THEN
  349.   G.Message = 15
  350.   G.Message = Lines(Who%%, 0, 1)
  351.   IF G.Message = 0 THEN G.Message = 360
  352.  G.Action = FALSE
  353.  
  354. SUB Run_Status
  355.  G.Display_Status = TRUE
  356.  G.Input_Wait = TRUE
  357.  
  358. SUB Run_search
  359.  STATIC dialog AS _BYTE
  360.  IF dialog = 1 THEN G.Message = 238: G.Action = FALSE: dialog = 0
  361.  IF dialog = 0 THEN G.Message = 237: dialog = dialog + 1
  362.  
  363. SUB Run_Spell
  364.  G.Message = 48
  365.  
  366. SUB Run_Item
  367.  G.Message = 60
  368.  
  369. SUB Run_Door
  370.  G.Message = 311 'no door
  371.  'g.message = 312 'no keys
  372.  
  373. SUB Run_Take
  374.  G.Message = 242
  375.  
  376.  
  377. SUB Run_Stairs
  378.  IF P(who%%).Map >= 0 THEN
  379.   IF Place(P(who%%).Map, P(who%%).MapX, P(who%%).MapY).Is_Stairs THEN
  380.    IF NOT F.Has_Left_Throne_Room THEN F.Has_Left_Throne_Room = TRUE 'if player has just started game
  381.  
  382.    IF Stairs(Place(P(who%%).Map, P(who%%).MapX, P(who%%).MapY).Is_Stairs).Direction = 1 THEN _SNDPLAY SFX(1) ELSE _SNDPLAY SFX(2)
  383.    P(who%%).Map = Stairs(Place(P(who%%).Map, P(who%%).MapX, P(who%%).MapY).Is_Stairs).Link
  384.    'get location information from the linked stair Record.
  385.    P(who%%).MapX = Stairs(P(who%%).Map).X
  386.    P(who%%).MapY = Stairs(P(who%%).Map).Y
  387.    IF Stairs(P(who%%).Map).Map = -1 THEN P(who%%).WorldX = Stairs(P(who%%).Map).X: P(who%%).WorldY = Stairs(P(who%%).Map).Y
  388.    P(who%%).Map = Stairs(P(who%%).Map).Map
  389.    IF P(who%%).Map >= 0 THEN Build_Place_Layer Layer(7), P(who%%).Map
  390.    Change_BGM 0
  391.    G.Menu = FALSE
  392.   ELSE
  393.    G.Message = 13
  394.   END IF
  395.   IF World(P(who%%).WorldX, P(who%%).WorldY).Is_Stairs THEN
  396.    IF Stairs(World(P(who%%).WorldX, P(who%%).WorldY).Is_Stairs).Direction = 1 THEN _SNDPLAY SFX(1) ELSE _SNDPLAY SFX(2)
  397.    P(who%%).Map = Stairs(World(P(who%%).WorldX, P(who%%).WorldY).Is_Stairs).Link
  398.    'get location information from the linked stair Record.
  399.    P(who%%).MapX = Stairs(P(who%%).Map).X
  400.    P(who%%).MapY = Stairs(P(who%%).Map).Y
  401.    P(who%%).Map = Stairs(P(who%%).Map).Map
  402.    Build_Place_Layer Layer(7), P(who%%).Map
  403.    G.Menu = FALSE
  404.    Change_BGM 0
  405.   ELSE
  406.    G.Message = 13
  407.   END IF
  408.  
  409.  
  410. SUB Check_Location_World (who%%)
  411.  
  412.  IF World(P(who%%).WorldX, P(who%%).WorldY).Is_Town AND G.In_Place = FALSE THEN
  413.   P(who%%).Map = World(P(who%%).WorldX, P(who%%).WorldY).Is_Town
  414.   IF P(who%%).Map = 1 THEN P(who%%).Map = 0
  415.   P(who%%).MapX = PD(P(who%%).Map).Start_X
  416.   P(who%%).MapY = PD(P(who%%).Map).Start_Y
  417.   Build_Place_Layer Layer(7), P(who%%).Map
  418.   Change_BGM 0
  419.   G.In_Place = TRUE
  420.  
  421.  IF World(P(who%%).WorldX, P(who%%).WorldY).Sprite_ID = 5 THEN _DELAY .05 'slow movement when crossing hills
  422.  
  423.  ' IF World(P(who%%).WorldX, P(who%%).WorldY).Is_Cave THEN P(who%%).Map = World(P(who%%).WorldX, P(who%%).WorldY).Is_Town
  424.  
  425. SUB Check_Location_Place (who%%)
  426.  IF Place(P(who%%).Map, P(who%%).MapX, P(who%%).MapY).Is_Exit THEN P(who%%).Map = -1: G.JustLeft = TRUE: Change_BGM 0
  427.  
  428. SUB Move_Cycle (Who%%)
  429.  STATIC Move AS _BYTE
  430.  Move = Move + 2
  431.  IF Move = 32 THEN Move = 0: G.Flag = FALSE
  432.  IF Move = 30 THEN Move_Player Who%%
  433.  SELECT CASE P(Who%%).Facing
  434.   CASE UP
  435.    G.Y = -Move
  436.   CASE RIGHT
  437.    G.X = Move
  438.   CASE LEFT
  439.    G.X = -Move
  440.   CASE DOWN
  441.    G.Y = Move
  442.  
  443. SUB Move_Player (who%%)
  444.  IF P(who%%).Map >= 0 THEN
  445.   SELECT CASE P(who%%).Facing
  446.    CASE UP
  447.     P(who%%).MapY = P(who%%).MapY - 1
  448.    CASE DOWN
  449.     P(who%%).MapY = P(who%%).MapY + 1
  450.    CASE LEFT
  451.     P(who%%).MapX = P(who%%).MapX - 1
  452.    CASE RIGHT
  453.     P(who%%).MapX = P(who%%).MapX + 1
  454.   Check_Location_Place who%%
  455.   SELECT CASE P(who%%).Facing
  456.    CASE UP
  457.     P(who%%).WorldY = P(who%%).WorldY - 1
  458.    CASE DOWN
  459.     P(who%%).WorldY = P(who%%).WorldY + 1
  460.    CASE LEFT
  461.     P(who%%).WorldX = P(who%%).WorldX - 1
  462.    CASE RIGHT
  463.     P(who%%).WorldX = P(who%%).WorldX + 1
  464.   IF G.JustLeft THEN G.JustLeft = FALSE
  465.   IF G.In_Place THEN G.In_Place = FALSE
  466.   Check_Location_World who%%
  467.  
  468. FUNCTION Controls%% (who%%)
  469.  STATIC Move_delay AS SINGLE
  470.  Result%% = FALSE
  471.  KBD& = _KEYHIT
  472.  
  473.  IF G.Menu = FALSE THEN
  474.   IF G.Selection <> 1 THEN G.Selection = 1
  475.   IF _KEYDOWN(Key_Right) AND (NOT G.Flag) THEN
  476.    G.LastMove = INT(TIMER + .49)
  477.    IF P(who%%).Facing <> RIGHT THEN P(who%%).Facing = RIGHT
  478.    IF Move_delay = 0 THEN
  479.     Move_delay = TIMER
  480.    ELSEIF TIMER > Move_delay + .125 THEN
  481.     IF NOT Collision(who%%, 1, 0) THEN G.Flag = TRUE
  482.    END IF
  483.   END IF
  484.   IF _KEYDOWN(Key_Left) AND (NOT G.Flag) THEN
  485.    G.LastMove = INT(TIMER + .49)
  486.    IF P(who%%).Facing <> LEFT THEN P(who%%).Facing = LEFT
  487.    IF Move_delay = 0 THEN
  488.     Move_delay = TIMER
  489.    ELSEIF TIMER > Move_delay + .125 THEN
  490.     IF NOT Collision(who%%, -1, 0) THEN G.Flag = TRUE
  491.    END IF
  492.   END IF
  493.   IF _KEYDOWN(Key_Up) AND (NOT G.Flag) THEN
  494.    G.LastMove = INT(TIMER + .49)
  495.    IF P(who%%).Facing <> UP THEN P(who%%).Facing = UP
  496.    IF Move_delay = 0 THEN
  497.     Move_delay = TIMER
  498.    ELSEIF TIMER > Move_delay + .125 THEN
  499.     IF NOT Collision(who%%, 0, -1) THEN G.Flag = TRUE
  500.    END IF
  501.   END IF
  502.   IF _KEYDOWN(Key_Down) AND (NOT G.Flag) THEN
  503.    G.LastMove = INT(TIMER + .49)
  504.    IF P(who%%).Facing <> DOWN THEN P(who%%).Facing = DOWN
  505.    IF Move_delay = 0 THEN
  506.     Move_delay = TIMER
  507.    ELSEIF TIMER > Move_delay + .125 THEN
  508.     IF NOT Collision(who%%, 0, 1) THEN G.Flag = TRUE
  509.    END IF
  510.   END IF
  511.  
  512.   IF KBD& = A_Button THEN G.Menu = TRUE: G.LastMove = G.LastMove - 2
  513.   IF (NOT _KEYDOWN(Key_Right)) AND (NOT _KEYDOWN(Key_Left)) AND (NOT _KEYDOWN(Key_Down)) AND (NOT _KEYDOWN(Key_Up)) THEN Move_delay = 0
  514.  
  515.  ELSEIF G.Input_Wait THEN
  516.  
  517.   IF KBD& = B_Button OR KBD& = A_Button THEN
  518.    G.Menu = FALSE: G.Input_Wait = FALSE: G.Message = 0: ClearLayer Layer(5): _CLEARCOLOR _RGB32(0, 0, 0), Layer(5)
  519.    IF G.Display_Status THEN G.Display_Status = FALSE
  520.   END IF
  521.   IF KBD& = Key_Up AND G.Selection > 1 AND G.Selection <> 5 THEN G.Selection = G.Selection - 1
  522.   IF KBD& = Key_Down AND G.Selection < 8 AND G.Selection <> 4 THEN G.Selection = G.Selection + 1
  523.   IF KBD& = Key_Left AND G.Selection > 4 THEN G.Selection = G.Selection - 4
  524.   IF KBD& = Key_Right AND G.Selection < 5 THEN G.Selection = G.Selection + 4
  525.  
  526.   IF KBD& = B_Button THEN G.Menu = FALSE
  527.   IF KBD& = A_Button THEN Process_Command
  528.  
  529.  IF KBD& = 27 THEN Result%% = TRUE
  530.  
  531.  Controls = Result%%
  532.  
  533.  
  534.  
  535. SUB Init_Player (Who%%)
  536.  '---------------Player starting stats-----------------------
  537.  P(Who%%).Max_HP = INT(RND * 8) + 12 'start 12-20hp
  538.  P(Who%%).HP = P(Who%%).Max_HP
  539.  IF INT(RND * 100) = 95 THEN P(Who%%).Max_MP = INT(RND * 3) + 4 '1 in 100 chance of starting with magical powers
  540.  P(Who%%).MP = P(Who%%).Max_MP
  541.  P(Who%%).Strength = INT(RND * 3) + 2 'determines base attack damage
  542.  P(Who%%).Agility = INT(RND * 2) + 2 'determines base defence\evasion
  543.  P(Who%%).Luck = INT(RND * 5) 'a "chance" bonus to hits and evasions
  544.  P(Who%%).Level = 0 'starting at base; first fight elevates to level 1, no xp gain though
  545.  P(Who%%).Age = 17 'level adds to age *1.5 (level 10 adds 15 to age, 20 adds 30, 30 adds 45, max age 72!)
  546.  ' age affects Strength by subtracting INT((-5 + (Age - 20)) * (.15 + ((Age-17)/100))-.49)  ;  youth gives strength
  547.  ' age affects Agility by subtracting INT((-8 + (Age - 20)) * (.4 + ((Age-17)/100))-.49)   ;  youth gives great agility, age loses agility quickly
  548.  ' age affects Luck by adding (0 + (Age - 25)) * (.4 + ((Age-17)/50))  ;  age adds luck
  549.  P(Who%%).Weapon = 0 'adds to Attack strength , start with Fists
  550.  P(Who%%).Armor = 8 'adds to Defensive strength , start with Loin Cloth
  551.  P(Who%%).Shield = 16 'adds to Defensive strength , start with None
  552.  P(Who%%).Gold = 0
  553.  P(Who%%).Exp = 0
  554.  P(Who%%).WorldX = 44
  555.  P(Who%%).WorldY = 44
  556.  P(Who%%).MapX = 17 'when starting game player always starts here
  557.  P(Who%%).MapY = 18
  558.  P(Who%%).Map = 1
  559.  '-----------------------------------------------------------
  560.  
  561. SUB Light_Effect
  562.  _DEST Layer(11)
  563.  CLS
  564.  SELECT CASE G.Lite_Level
  565.   CASE 0 'can only see player
  566.    LINE (256, 224)-STEP(32, 32), _RGB(1, 1, 1), BF
  567.   CASE 1 'one block around player visable
  568.    LINE (224, 192)-STEP(96, 96), _RGB(1, 1, 1), BF
  569.   CASE 2 'two blocks around player
  570.    LINE (192, 176)-STEP(144, 144), _RGB(1, 1, 1), BF
  571.   CASE 3 'three blocks around player
  572.    LINE (160, 144)-STEP(208, 208), _RGB(1, 1, 1), BF
  573.  _CLEARCOLOR _RGB32(1, 1, 1), Layer(11)
  574.  
  575. SUB Message_Handler (L&, MSG$)
  576.  STATIC Message_Length AS _UNSIGNED _BYTE
  577.  STATIC Current_Char AS _BYTE
  578.  STATIC Processed AS STRING, LineCount AS _BYTE, MYL AS _BYTE
  579.  STATIC Lines(10) AS STRING * 22, Slowit AS _BYTE
  580.  
  581.  IF NOT G.Input_Wait THEN
  582.   IF Message_Length = 0 THEN 'start of new message
  583.    F.Message_Displaying = TRUE
  584.    MYL = 1
  585.    IF INSTR(Script(G.Message), "#") THEN
  586.     Processed = Process_Message_Coding$(Script(G.Message)): Message_Length = LEN(Processed)
  587.    ELSE
  588.     Message_Length = LEN(Script(G.Message))
  589.     Processed = Script(G.Message)
  590.    END IF
  591.   END IF
  592.   'check message length word wrap if needed
  593.   IF Message_Length > 22 AND LineCount = 0 THEN LineCount = Process_Word_Wrap(Lines(), Processed)
  594.   IF Message_Length <= 22 THEN LineCount = 1: Lines(1) = Processed
  595.   Slowit = Slowit + 1
  596.   IF Slowit = 4 THEN Slowit = 0: Current_Char = Current_Char + 1: _SNDPLAY SFX(3)
  597.  
  598.   _PRINTSTRING (80, 288 + 16 * MYL), MID$(Lines(MYL), 1, Current_Char), L& 'print message 1 character at a time.
  599.  
  600.   IF Current_Char = LEN(RTRIM$(Lines(MYL))) THEN MYL = MYL + 1: Current_Char = 0
  601.   IF MYL = LineCount + 1 THEN 'if the message is done then reset everything and wait for input
  602.    G.Input_Wait = TRUE: Processed = "": Message_Length = 0
  603.    MYL = 0: Lines(1) = "": LineCount = 0
  604.    F.Message_Displaying = FALSE
  605.   END IF
  606.  
  607.  
  608. FUNCTION Process_Message_Coding$ (Txt$)
  609.  FOR i~%% = 1 TO LEN(Txt$) 'check message for formating
  610.   IF MID$(Txt$, i~%%, 1) = "#" THEN
  611.    SELECT CASE MID$(Txt$, i~%% + 1, 1)
  612.     CASE "E"
  613.      Result$ = Result$ + RTRIM$(M(battle%%).Nam)
  614.      i~%% = i~%% + 1
  615.     CASE "P"
  616.      Result$ = Result$ + RTRIM$(P(who%%).Nam)
  617.      i~%% = i~%% + 1
  618.     CASE "I"
  619.      Result$ = Result$ + RTRIM$(I(which%%).Nam)
  620.      i~%% = i~%% + 1
  621.     CASE "N"
  622.      'Processed = Processed + MID$(Script(G.Message), i~%%, 1)
  623.    END SELECT
  624.   ELSEIF MID$(Txt$, i~%%, 1) = "&" THEN
  625.    SELECT CASE MID$(Txt$, i~%% + 1, 1)
  626.     CASE "Y"
  627.      G.YES_NO_Input = TRUE
  628.      i~%% = i~%% + 1
  629.    END SELECT
  630.   ELSE
  631.    Result$ = Result$ + MID$(Txt$, i~%%, 1)
  632.   END IF
  633.  NEXT i~%%
  634.  
  635.  Process_Message_Coding = Result$
  636.  
  637.  
  638.  
  639. SUB Control_setup
  640.  _PUTIMAGE (40, 32), Layer(10), Layer(0)
  641.  'up arrow
  642.  LINE (128, 128)-(32, 132), _RGB32(255, 127, 0), BF
  643.  LINE (32, 132)-(36, 460), _RGB32(255, 127, 0), BF
  644.  LINE (32, 460)-(212, 464), _RGB32(255, 127, 0), BF
  645.  'left arrow
  646.  LINE (92, 160)-(48, 164), _RGB32(92, 192, 0), BF
  647.  LINE (48, 164)-(52, 416), _RGB32(92, 192, 0), BF
  648.  LINE (48, 416)-(240, 420), _RGB32(92, 192, 0), BF
  649.  'down arrow
  650.  LINE (128, 212)-(64, 216), _RGB32(0, 127, 255), BF
  651.  LINE (64, 216)-(68, 372), _RGB32(0, 127, 255), BF
  652.  LINE (64, 372)-(256, 376), _RGB32(0, 127, 255), BF
  653.  'right arrow
  654.  LINE (176, 184)-(180, 240), _RGB32(0, 64, 160), BF
  655.  LINE (80, 240)-(180, 244), _RGB32(0, 64, 160), BF
  656.  LINE (80, 244)-(84, 326), _RGB32(0, 64, 160), BF
  657.  LINE (80, 326)-(260, 330), _RGB32(0, 64, 160), BF
  658.  'select
  659.  LINE (264, 212)-(268, 460), _RGB32(255, 64, 0), BF
  660.  LINE (264, 460)-(416, 464), _RGB32(255, 64, 0), BF
  661.  'start
  662.  LINE (328, 212)-(332, 416), _RGB32(212, 0, 16), BF
  663.  LINE (328, 416)-(496, 420), _RGB32(212, 0, 16), BF
  664.  'B Button
  665.  LINE (426, 208)-(430, 256), _RGB32(64, 92, 212), BF
  666.  LINE (340, 256)-(430, 260), _RGB32(64, 92, 212), BF
  667.  LINE (340, 260)-(344, 376), _RGB32(64, 92, 212), BF
  668.  LINE (340, 372)-(496, 376), _RGB32(64, 92, 212), BF
  669.  'A Button
  670.  LINE (496, 208)-(500, 272), _RGB32(80, 64, 180), BF
  671.  LINE (356, 272)-(500, 276), _RGB32(80, 64, 180), BF
  672.  LINE (356, 272)-(360, 328), _RGB32(80, 64, 180), BF
  673.  LINE (356, 328)-(528, 332), _RGB32(80, 64, 180), BF
  674.  
  675.  IF Key_Up = 18432 THEN _PRINTSTRING (64, 440), "Up Arrow"
  676.  IF Key_Down = 20480 THEN _PRINTSTRING (96, 352), "Down Arrow"
  677.  IF Key_Left = 19200 THEN _PRINTSTRING (80, 396), "Left Arrow"
  678.  IF Key_Right = 19712 THEN _PRINTSTRING (112, 308), "Right Arrow"
  679.  IF A_Button = 32 THEN _PRINTSTRING (388, 308), "Space Bar"
  680.  IF B_Button = 13 THEN _PRINTSTRING (370, 352), "Enter"
  681.  _PRINTSTRING (296, 440), CHR$(Select_Button)
  682.  _PRINTSTRING (364, 396), CHR$(Start_Button)
  683.  LOCATE 1, 1: PRINT "Press any key"
  684.  
  685. SUB MFI_Loader (FN$)
  686.  DIM Size(64) AS LONG, FOffset(64) AS LONG
  687.  GET #1, , c~%% 'retrieve number of files
  688.  FOR I~%% = 1 TO c~%%
  689.   GET #1, , FOffset(I~%%)
  690.   GET #1, , Size(I~%%)
  691.   FOffset&(I~%%) = FOffset&(I~%%) + 1
  692.  NEXT I~%%
  693.  Layer(10) = LoadGFX(FOffset(1), Size(1))
  694.  Layer(3) = LoadGFX(FOffset(2), Size(2))
  695.  Layer(4) = LoadGFX(FOffset(3), Size(3))
  696.  BGM(-1) = LoadSFX(FOffset(4), Size(4))
  697.  BGM(0) = LoadSFX(FOffset(10), Size(10))
  698.  BGM(1) = LoadSFX(FOffset(12), Size(12))
  699.  BGM(3) = LoadSFX(FOffset(12), Size(12))
  700.  SFX(0) = LoadSFX(FOffset(5), Size(5))
  701.  SFX(1) = LoadSFX(FOffset(8), Size(8))
  702.  SFX(2) = LoadSFX(FOffset(9), Size(9))
  703.  SFX(3) = LoadSFX(FOffset(11), Size(11))
  704.  LoadData FOffset(6), Size(6)
  705.  DWFont = LoadFFX(FOffset(7), Size(7), 16)
  706.  
  707.  IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
  708.  
  709. FUNCTION LoadGFX& (Foff&, Size&)
  710.  IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
  711.  OPEN "temp.dat" FOR BINARY AS #3
  712.  dat$ = SPACE$(Size&)
  713.  GET #1, Foff&, dat$
  714.  PUT #3, , dat$
  715.  CLOSE #3
  716.  LoadGFX& = _LOADIMAGE("temp.dat", 32)
  717.  
  718. FUNCTION LoadFFX& (Foff&, Size&, Fize%%)
  719.  IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
  720.  OPEN "temp.dat" FOR BINARY AS #3
  721.  dat$ = SPACE$(Size&)
  722.  GET #1, Foff&, dat$
  723.  PUT #3, , dat$
  724.  CLOSE #3
  725.  LoadFFX& = _LOADFONT("temp.dat", Fize%%, "monospace")
  726.  
  727. FUNCTION LoadSFX& (Foff&, Size&)
  728.  IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
  729.  OPEN "temp.dat" FOR BINARY AS #3
  730.  dat$ = SPACE$(Size&)
  731.  GET #1, Foff&, dat$
  732.  PUT #3, , dat$
  733.  CLOSE #3
  734.  LoadSFX& = _SNDOPEN("temp.dat")
  735.  
  736. SUB LoadData (Foff&, Size&)
  737.  IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
  738.  OPEN "temp.dat" FOR BINARY AS #3
  739.  dat$ = SPACE$(Size&)
  740.  GET #1, Foff&, dat$
  741.  PUT #3, , dat$
  742.  CLOSE #3
  743.  
  744.  F1 = FREEFILE
  745.  OPEN "temp.dat" FOR BINARY AS #F1
  746.  ' OPEN "GameDataV1_1b.dat" FOR BINARY AS #1
  747.  GET #F1, , World()
  748.  GET #F1, , Place()
  749.  GET #F1, , I()
  750.  GET #F1, , L()
  751.  GET #F1, , GF()
  752.  GET #F1, , M()
  753.  GET #F1, , Stairs()
  754.  GET #F1, , PD()
  755.  GET #F1, , Chest()
  756.  FOR i% = 1 TO 360
  757.   GET #F1, , L~%%
  758.   Script(i%) = SPACE$(L~%%)
  759.   GET #F1, , Script(i%)
  760.  NEXT i%
  761.  GET #F1, , NPC()
  762.  GET #F1, , Lines()
  763.  CLOSE #F1
  764.  
  765.  
  766. SUB Change_BGM (who%%)
  767.  IF P(who%%).Map <> G.Current_BGM THEN
  768.   _SNDSTOP BGM(G.Current_BGM) 'stop the old music
  769.   _DELAY .15
  770.   _SNDLOOP BGM(P(who%%).Map) ' start the new music
  771.   G.Current_BGM = P(who%%).Map ' store which music is now playing
  772.  
  773. SUB ClearLayerADV (L&)
  774.  STATIC ML1 AS _MEM
  775.  ML1 = _MEMIMAGE(L&)
  776.  _MEMPUT ML1, ML1.OFFSET, _MEMGET(ClearLayerMaster, ClearLayerMaster.OFFSET, STRING * 8667136)
  777.  
  778. FUNCTION Find_NPC%% (Direction%%)
  779.  Result%% = -1
  780.  X%% = 0: Y%% = 0
  781.  SELECT CASE Direction%%
  782.   CASE UP
  783.    Y%% = -1
  784.   CASE DOWN
  785.    Y%% = 1
  786.   CASE LEFT
  787.    X%% = -1
  788.   CASE RIGHT
  789.    X%% = 1
  790.  
  791.  FOR i%% = 0 TO 120
  792.   IF NPC(i%%).Map = P(0).Map THEN
  793.    IF NPC(i%%).X = P(0).MapX + X%% AND NPC(i%%).Y = P(0).MapY + Y%% THEN Result%% = i%%: i%% = 127
  794.   END IF
  795.   IF NPC(i%%).X = 0 THEN i%% = 127
  796.  NEXT i%%
  797.  Find_NPC = Result%%
  798.  
  799. SUB NPC_Monologue (Who%%)
  800.  old%% = NPC(Who%%).Moving
  801.  NPC(Who%%).Moving = FALSE 'make sure NPC does not walk away while we are talking to them
  802.  G.Message = Lines(Who%%, 0, 1)
  803.  DO
  804.   '  IF INKEY$ = CHR$(27) THEN exitflag%% = TRUE
  805.   IF NOT F.Message_Displaying THEN Result%% = Controls(0)
  806.   IF Result%% = TRUE THEN ExitFlag%% = TRUE
  807.   IF NOT G.Input_Wait THEN
  808.    Draw_Info_Window Layer(1): Message_Handler Layer(5), ""
  809.   ELSE
  810.  
  811.   END IF
  812.  
  813.   Debuginfo
  814.  
  815.   _PUTIMAGE , Layer(5), Layer(1)
  816.   _PUTIMAGE , Layer(9), Layer(1)
  817.   _PUTIMAGE , Layer(1), Layer(0)
  818.   Process_NPC
  819.   _LIMIT 60
  820.   Frames% = Frames% + 1
  821.  
  822.  
  823.  
  824.  LOOP UNTIL ExitFlag%%
  825.  
  826.  G.Input_Wait = FALSE
  827.  ClearLayer Layer(5)
  828.  G.Message = 0
  829.  NPC(Who%%).Moving = old%%
  830.  
  831. FUNCTION YES_NO_Box
  832.  G.YES_NO_Input = TRUE
  833.  
  834.  
  835. REM'$include:'FinishedRoutines.bas'
  836. FUNCTION Collision%% (Who%%, X%%, Y%%)
  837.  Result%% = TRUE
  838.  IF P(Who%%).Map >= 0 THEN 'check place map
  839.   SELECT CASE Place(P(Who%%).Map, P(Who%%).MapX + X%%, P(Who%%).MapY + Y%%).Sprite_ID
  840.    CASE 0 TO 13
  841.     Result%% = FALSE
  842.    CASE ELSE
  843.     IF NOT _SNDPLAYING(SFX(0)) THEN _SNDPLAY SFX(0)
  844.  
  845.   IF NOT Result%% THEN 'check for NPC collision
  846.    FOR i%% = 0 TO 120 '<--update when actual NPC count is known
  847.     IF P(Who%%).MapX + X%% = NPC(i%%).X AND P(Who%%).MapY + Y%% = NPC(i%%).Y AND P(Who%%).Map = NPC(i%%).Map THEN
  848.      Result%% = TRUE: i%% = 122
  849.      IF NOT _SNDPLAYING(SFX(0)) THEN _SNDPLAY SFX(0)
  850.     END IF
  851.     IF NPC(i%%).X = 0 THEN i%% = 122 'no NPC can occupy a 0 location so we know we are past the last NPC
  852.    NEXT i%%
  853.   END IF
  854.  
  855.  ELSE 'check world map
  856.   SELECT CASE World(P(Who%%).WorldX + X%%, P(Who%%).WorldY + Y%%).Sprite_ID
  857.    CASE 0 TO 13
  858.     Result%% = FALSE
  859.    CASE ELSE
  860.     IF NOT _SNDPLAYING(SFX(0)) THEN _SNDPLAY SFX(0)
  861.  Collision = Result%%
  862.  
  863. SUB Frame_Change
  864.  IF Frame%% THEN Frame%% = 0 ELSE Frame%% = 1
  865.  
  866. SUB Copy_Map_Layer (L&, MX%%, MY%%)
  867.  IF P(0).Map >= 0 THEN
  868.   _PUTIMAGE (16, 16), L&, Layer(1), (MX%% * 32 - 240 + G.X, MY%% * 32 - 208 + G.Y)-STEP(495, 447)
  869.   _PUTIMAGE (16, 16), L&, Layer(1), (128 + MX%% * 32 - 240 + G.X, 128 + MY%% * 32 - 208 + G.Y)-STEP(495, 447)
  870.  
  871. SUB ClearLayer (L&)
  872.  old& = _DEST
  873.  _DEST L&
  874.  CLS
  875.  _DEST old&
  876.  
  877. SUB Draw_Window (X%%, Y%%, Xs%%, Ys%%, L&)
  878.  'top corners of window
  879.  _PUTIMAGE (X%% * 16, Y%% * 16)-STEP(15, 15), Layer(3), L&, (0, 18)-STEP(7, 7)
  880.  _PUTIMAGE (X%% * 16 + Xs%% * 16, Y%% * 16)-STEP(15, 15), Layer(3), L&, (8, 18)-STEP(7, 7)
  881.  'bottom corners of window
  882.  _PUTIMAGE (X%% * 16, Y%% * 16 + Ys%% * 16)-STEP(15, 15), Layer(3), L&, (16, 18)-STEP(7, 7)
  883.  _PUTIMAGE (X%% * 16 + Xs%% * 16, Y%% * 16 + Ys%% * 16)-STEP(15, 15), Layer(3), L&, (24, 18)-STEP(7, 7)
  884.  'top and bottom of window
  885.  FOR i%% = 1 TO Xs%% - 1
  886.   _PUTIMAGE (X%% * 16 + i%% * 16, Y%% * 16)-STEP(15, 15), Layer(3), L&, (56, 18)-STEP(7, 7)
  887.   _PUTIMAGE (X%% * 16 + i%% * 16, Y%% * 16 + Ys%% * 16)-STEP(15, 15), Layer(3), L&, (48, 18)-STEP(7, 7)
  888.  NEXT i%%
  889.  'left and right sides of window
  890.  FOR i%% = 1 TO Ys%% - 1
  891.   _PUTIMAGE (X%% * 16, Y%% * 16 + 16 * i%%)-STEP(15, 15), Layer(3), L&, (32, 18)-STEP(7, 7)
  892.   _PUTIMAGE (X%% * 16 + Xs%% * 16, Y%% * 16 + 16 * i%%)-STEP(15, 15), Layer(3), L&, (40, 18)-STEP(7, 7)
  893.  NEXT i%%
  894.  'fill in window
  895.  _PUTIMAGE ((X%% + 1) * 16, (Y%% + 1) * 16)-STEP((Xs%% - 1) * 16, (Ys%% - 1) * 16), Layer(3), L&, (307, 1)-STEP(15, 15)
  896.  
  897. SUB Draw_Command_Window (L&)
  898.  Draw_Window 12, 2, 15, 9, Layer(1)
  899.  _PUTIMAGE (16 * 16 - 2, 2 * 16)-STEP(7 * 15 + 4, 1 * 15), Layer(3), Layer(1), (205, 35)-STEP(15, 15)
  900.  _PRINTSTRING (16 * 16, 16 * 2), "COMMAND", L&
  901.  _PRINTSTRING (16 * 14, 16 * 4), "TALK", L&
  902.  _PRINTSTRING (16 * 14, 16 * 6), "STATUS", L&
  903.  _PRINTSTRING (16 * 14, 16 * 8), "STAIRS", L&
  904.  _PRINTSTRING (16 * 14, 16 * 10), "SEARCH", L&
  905.  _PRINTSTRING (16 * 22, 16 * 4), "SPELL", L&
  906.  _PRINTSTRING (16 * 22, 16 * 6), "ITEM", L&
  907.  _PRINTSTRING (16 * 22, 16 * 8), "DOOR", L&
  908.  _PRINTSTRING (16 * 22, 16 * 10), "TAKE", L&
  909.  Display_Selection_Arrow SA(G.Selection).X, SA(G.Selection).Y, L&
  910.  
  911. SUB Display_Selection_Arrow (X%%, Y%%, L&)
  912.  _PUTIMAGE (X%% * 16, Y%% * 16)-STEP(15, 15), Layer(3), L&, (64, 18)-STEP(7, 7)
  913.  
  914. SUB Draw_Stat_Window (L&, Who%%)
  915.  Draw_Window 2, 4, 7, 11, Layer(1)
  916.  _PUTIMAGE (4 * 16 - 2, 4 * 16)-STEP(4 * 15 + 4, 1 * 15), Layer(3), Layer(1), (205, 35)-STEP(15, 15)
  917.  _PRINTSTRING (16 * 4, 16 * 4), LEFT$(P(Who%%).Nam, 4), L&
  918.  _PRINTSTRING (16 * 3, 16 * 6), "LV", L&
  919.  _PRINTSTRING (16 * 3, 16 * 8), "HP", L&
  920.  _PRINTSTRING (16 * 3, 16 * 10), "MP", L&
  921.  _PRINTSTRING (16 * 3, 16 * 12), "G", L&
  922.  _PRINTSTRING (16 * 3, 16 * 14), "E", L&
  923.  _PRINTSTRING (16 * (9 - LEN(STR$(P(Who%%).Level))), 16 * 6), STR$(P(Who%%).Level), L&
  924.  _PRINTSTRING (16 * (9 - LEN(STR$(P(Who%%).HP))), 16 * 8), (STR$(P(Who%%).HP)), L&
  925.  _PRINTSTRING (16 * (9 - LEN(STR$(P(Who%%).MP))), 16 * 10), STR$(P(Who%%).MP), L&
  926.  _PRINTSTRING (16 * (9 - LEN(STR$(P(Who%%).Gold))), 16 * 12), STR$(P(Who%%).Gold), L&
  927.  _PRINTSTRING (16 * (9 - LEN(STR$(P(Who%%).Exp))), 16 * 14), STR$(P(Who%%).Exp), L&
  928.  
  929. SUB Draw_Info_Window (L&)
  930.  Draw_Window 4, 18, 23, 9, L&
  931.  
  932. SUB Build_World_Layer (L&)
  933.  FOR Y~%% = 0 TO 255
  934.   FOR X~%% = 0 TO 255
  935.    _PUTIMAGE (32 * X~%%, 32 * Y~%%)-STEP(31, 31), Layer(3), L&, (1 + 17 * 14, 1)-STEP(15, 15)
  936.  NEXT X~%%, Y~%%
  937.  FOR Y%% = 0 TO 121
  938.   FOR X%% = 0 TO 121
  939.    _PUTIMAGE (128 + 32 * X%%, 128 + 32 * Y%%)-STEP(31, 31), Layer(3), L&, (1 + 17 * World(X%%, Y%%).Sprite_ID, 1)-STEP(15, 15)
  940.  NEXT X%%, Y%%
  941.  
  942. SUB Build_Place_Layer (L&, ID%%)
  943.  FOR Y%% = 0 TO 45
  944.   FOR X%% = 0 TO 45
  945.    _PUTIMAGE (0 + 32 * X%%, 0 + 32 * Y%%)-STEP(31, 31), Layer(3), L&, (1 + 17 * Place(ID%%, X%%, Y%%).Sprite_ID, 1)-STEP(15, 15)
  946.  NEXT X%%, Y%%
  947.  
  948. SUB Display_Player_Status (L&)
  949.  Draw_Window 10, 6, 19, 21, L&
  950.  _PRINTSTRING (16 * 16, 16 * 7), "NAME:" + RTRIM$(P(who%%).Nam), L&
  951.  _PRINTSTRING (16 * 17, 16 * 9), "STRENGTH:", L&
  952.  _PRINTSTRING (16 * 18, 16 * 11), "AGILITY:", L&
  953.  _PRINTSTRING (16 * 15, 16 * 13), "MAXIMUM HP:", L&
  954.  _PRINTSTRING (16 * 15, 16 * 15), "MAXIMUM MP:", L&
  955.  _PRINTSTRING (16 * 13, 16 * 17), "ATTACK POWER:", L&
  956.  _PRINTSTRING (16 * 12, 16 * 19), "DEFENSE POWER:", L&
  957.  _PRINTSTRING (16 * 13, 16 * 21), "WEAPON:", L&
  958.  _PRINTSTRING (16 * 14, 16 * 23), "ARMOR:", L&
  959.  _PRINTSTRING (16 * 13, 16 * 25), "SHIELD:", L&
  960.  V1$ = LTRIM$(STR$(P(who%%).Strength))
  961.  _PRINTSTRING (16 * (26 + (3 - LEN(V1$))), 16 * 9), V1$, L&
  962.  V1$ = LTRIM$(STR$(P(who%%).Agility))
  963.  _PRINTSTRING (16 * (26 + (3 - LEN(V1$))), 16 * 11), V1$, L&
  964.  V1$ = LTRIM$(STR$(P(who%%).Max_HP))
  965.  _PRINTSTRING (16 * (26 + (3 - LEN(V1$))), 16 * 13), V1$, L&
  966.  V1$ = LTRIM$(STR$(P(who%%).Max_MP))
  967.  _PRINTSTRING (16 * (26 + (3 - LEN(V1$))), 16 * 15), V1$, L&
  968.  V1$ = LTRIM$(STR$(Player_Attack(who%%)))
  969.  _PRINTSTRING (16 * (26 + (3 - LEN(V1$))), 16 * 17), V1$, L&
  970.  V1$ = LTRIM$(STR$(Player_Defense(who%%)))
  971.  _PRINTSTRING (16 * (26 + (3 - LEN(V1$))), 16 * 19), V1$, L&
  972.  
  973.  IF LEN(RTRIM$(I(P(who%%).Weapon).Nam)) < 9 THEN
  974.   V1$ = RTRIM$(I(P(who%%).Weapon).Nam)
  975.   _PRINTSTRING (16 * (20), 16 * 21), V1$, L&
  976.   V1$ = MID$(I(P(who%%).Weapon).Nam, 1, INSTR(I(P(who%%).Weapon).Nam, CHR$(32)))
  977.   _PRINTSTRING (16 * (20), 16 * 21), V1$, L&
  978.   V2$ = RTRIM$(MID$(I(P(who%%).Weapon).Nam, INSTR(I(P(who%%).Weapon).Nam, CHR$(32))))
  979.   _PRINTSTRING (16 * (20), 16 * 22), V2$, L&
  980.  
  981.  IF LEN(RTRIM$(I(P(who%%).Armor).Nam)) < 9 THEN
  982.   V1$ = RTRIM$(I(P(who%%).Armor).Nam)
  983.   _PRINTSTRING (16 * (20), 16 * 23), V1$, L&
  984.   V1$ = MID$(I(P(who%%).Armor).Nam, 1, INSTR(I(P(who%%).Armor).Nam, CHR$(32)))
  985.   _PRINTSTRING (16 * (20), 16 * 23), V1$, L&
  986.   V2$ = RTRIM$(MID$(I(P(who%%).Armor).Nam, INSTR(I(P(who%%).Armor).Nam, CHR$(32))))
  987.   _PRINTSTRING (16 * (20), 16 * 24), V2$, L&
  988.  
  989.  IF LEN(RTRIM$(I(P(who%%).Shield).Nam)) < 9 THEN
  990.   V1$ = RTRIM$(I(P(who%%).Shield).Nam)
  991.   _PRINTSTRING (16 * (20), 16 * 25), V1$, L&
  992.   V1$ = MID$(I(P(who%%).Shield).Nam, 1, INSTR(I(P(who%%).Shield).Nam, CHR$(32)))
  993.   _PRINTSTRING (16 * (20), 16 * 25), V1$, L&
  994.   V2$ = RTRIM$(MID$(I(P(who%%).Shield).Nam, INSTR(I(P(who%%).Shield).Nam, CHR$(32))))
  995.   _PRINTSTRING (16 * (20), 16 * 26), V2$, L&
  996.  
  997.  
  998. SUB Copy_NPC_Layer (L&, MX%%, MY%%)
  999.  _PUTIMAGE (16, 16), L&, Layer(1), (MX%% * 32 - 240 + G.X, MY%% * 32 - 208 + G.Y)-STEP(495, 447)
  1000.  
  1001. FUNCTION Process_Word_Wrap (Lines() AS STRING * 22, txt$)
  1002.  Result%% = 1: I%% = 1
  1003.  DO
  1004.   'start on character 22 and work back to a space
  1005.   x%% = 22: Space%% = FALSE
  1006.   DO
  1007.    IF MID$(txt$, x%%, 1) <> CHR$(32) THEN x%% = x%% - 1 ELSE Space%% = TRUE
  1008.    IF x%% = 0 AND I%% = 1 THEN PRINT "ERROR": END
  1009.   LOOP UNTIL Space%%
  1010.   Lines(I%%) = MID$(txt$, 1, x%%)
  1011.   txt$ = MID$(txt$, x%% + 1)
  1012.   I%% = I%% + 1
  1013.   IF LEN(txt$) <= 22 THEN GoodLength%% = TRUE
  1014.  LOOP UNTIL GoodLength%%
  1015.  Lines(I%%) = txt$ 'put the last of the text into a line
  1016.  Result%% = I%%
  1017.  Process_Word_Wrap = Result%%
  1018.  
  1019. SUB Put_Player_In_Place (Who%%)
  1020.  'build map of players location
  1021.  Build_Place_Layer Layer(7), P(Who%%).Map
  1022.  'place player at entry point
  1023.  P(Who%%).MapX = PD(P(Who%%).Map).Start_X
  1024.  P(Who%%).MapY = PD(P(Who%%).Map).Start_Y
  1025.  
  1026. SUB Draw_Player_Sprite (Who%%, L&)
  1027.  IF P(Who%%).Weapon AND P(Who%%).Shield > 16 THEN 'pick which sprite set to use
  1028.   Y1%% = 3 'has a shield and weapon
  1029.  ELSEIF P(Who%%).Weapon THEN
  1030.   Y1%% = 1 'only has weapon
  1031.  ELSEIF P(Who%%).Shield > 16 THEN 'No sheild is 16
  1032.   Y1%% = 2 'on has shield
  1033.   Y1%% = 0 'has nothing
  1034.  IF P(Who%%).Armor > 9 THEN Y1%% = Y1%% + 4 'player has armor
  1035.  
  1036.  IF P(Who%%).Has_Princess THEN Y1%% = 8 'if player is returning princess over-ride tile set
  1037.  
  1038.  SX% = 3 + (Frame%% * 16) + (P(Who%%).Facing * 32)
  1039.  SY% = 4 + (Y1%% * 18)
  1040.  _PUTIMAGE (256, 224)-STEP(31, 31), Layer(4), L&, (SX%, SY%)-STEP(15, 15)
  1041.  
  1042. SUB Draw_NPC_Sprites (Who%%, Count%%, L&)
  1043.  ClearLayerADV L&
  1044.  FOR i%% = 0 TO Count%%
  1045.   IF P(Who%%).Map = NPC(i%%).Map THEN
  1046.    SX% = 3 + (Frame%% * 16) + (NPC(i%%).Facing * 32)
  1047.    SY% = 4 + (NPC(i%%).Sprite_ID * 18)
  1048.    _PUTIMAGE (NPC(i%%).X * 32 + NPC(i%%).MX, NPC(i%%).Y * 32 + NPC(i%%).MY)-STEP(31, 31), Layer(4), L&, (SX%, SY%)-STEP(15, 15)
  1049.   END IF
  1050.  NEXT i%%
  1051.  
  1052. REM'$include:'CoreFunctions.bas'
  1053. SUB Add_To_Inventory (Who%%, Item%%, Count%%)
  1054.  STATIC m AS _MEM 'no need to initialize/free it over and over
  1055.  m = _MEM(P(Who%%)) 'Just change where you want to point it to.
  1056.  Pack = m.OFFSET + 28 'æmove to where P(Who%%).Pack starts at in memory
  1057.  
  1058.  Match%% = FALSE
  1059.  FOR i%% = 0 TO 15
  1060.   IF Item%% = _MEMGET(m, Pack + i%% * 2, _BYTE) THEN Match%% = i%%: i%% = 30
  1061.  NEXT i%%
  1062.  IF NOT Match%% THEN 'new item
  1063.   _MEMPUT m, Pack + P(Who%%).Items * 2, Item%% 'POKE
  1064.   _MEMPUT m, Pack + P(Who%%).Items * 2 + 1, Count%% 'POKE
  1065.   P(Who%%).Items = P(Who%%).Items + 1
  1066.   temp%% = _MEMGET(m, Pack + Match%% * 2 + 1, _BYTE)
  1067.   temp%% = temp%% + 1
  1068.   _MEMPUT m, Pack + Match%% * 2 + 1, Count%% 'POKE
  1069.  
  1070. SUB Remove_Inventory (who%%, Item%%, Count%%)
  1071.  STATIC m AS _MEM 'no need to initialize/free it over and over
  1072.  m = _MEM(P(who%%)) 'Just change where you want to point it to.
  1073.  Pack = m.OFFSET + 28 'æmove to where P(Who%%).Pack starts at in memory
  1074.  
  1075.  Match%% = FALSE
  1076.  FOR i%% = 0 TO 15 'find the item
  1077.   IF Item%% = _MEMGET(m, Pack + i%% * 2, _BYTE) THEN Match%% = i%%: i%% = 30
  1078.  NEXT i%%
  1079.  IF Match%% = FALSE THEN
  1080.   'something went horribly wrong!
  1081.   temp%% = _MEMGET(m, Pack + Match%% * 2 + 1, _BYTE)
  1082.   temp%% = temp%% - Count%%
  1083.  
  1084.   IF temp%% = 0 THEN 'item is out so remove from inventory
  1085.    temp$ = _MEMGET(m, Pack, STRING * 32) 'get entire pack string
  1086.    temp$ = LEFT$(temp$, Match%% * 2) + MID$(temp$, 2 * Match%% + 3)
  1087.    P(who%%).Items = P(who%%).Items - 1
  1088.  
  1089.    l%% = LEN(temp$)
  1090.    FOR i%% = l%% TO 31 'pad temp$ to full 32 characters
  1091.     temp$ = temp$ + CHR$(0)
  1092.    NEXT i%%
  1093.  
  1094.    _MEMPUT m, Pack, temp$ 'put invetory back
  1095.   ELSE
  1096.    _MEMPUT m, Pack + Match%% * 2 + 1, temp%% 'put adjusted count back
  1097.   END IF
  1098.  
  1099. SUB Drop_Inventory (Who%%, ID%%)
  1100.  STATIC m AS _MEM 'no need to initialize/free it over and over
  1101.  m = _MEM(P(Who%%)) 'Just change where you want to point it to.
  1102.  Pack = m.OFFSET + 28 'æmove to where P(Who%%).Pack starts at in memory
  1103.  
  1104.  Match%% = FALSE
  1105.  FOR i%% = 0 TO 15 'find the item
  1106.   IF ID%% = _MEMGET(m, Pack + i%% * 2, _BYTE) THEN Match%% = i%%: i%% = 30
  1107.  NEXT i%%
  1108.  IF Match%% = FALSE THEN
  1109.   'something went horribly wrong!
  1110.   temp$ = _MEMGET(m, Pack, STRING * 32) 'get entire pack string
  1111.   temp$ = LEFT$(temp$, Match%% * 2) + MID$(temp$, 2 * Match%% + 3)
  1112.   P(Who%%).Items = P(Who%%).Items - 1
  1113.  
  1114.   l%% = LEN(temp$)
  1115.   FOR i%% = l%% TO 31 'pad temp$ to full 32 characters
  1116.    temp$ = temp$ + CHR$(0)
  1117.   NEXT i%%
  1118.  
  1119.   _MEMPUT m, Pack, temp$ 'put invetory back
  1120.  
  1121. SUB Level_Up (Who%%)
  1122.  P(Who%%).Level = P(Who%%).Level + 1
  1123.  P(Who%%).Age = P(Who%%).Age + INT(P(Who%%).Level * 1.5 - .49)
  1124.  P(Who%%).Strength = P(Who%%).Strength + INT(RND * 6) + 1 - INT((-5 + (P(Who%%).Age - 20)) * (.15 + ((P(Who%%).Age - 17) / 100)) - .49)
  1125.  P(Who%%).Agility = P(Who%%).Agility + INT(RND * 6) + 1 - INT((-8 + (P(Who%%).Age - 20)) * (.4 + ((P(Who%%).Age - 17) / 100)) - .49)
  1126.  P(Who%%).Luck = P(Who%%).Luck + INT(RND * 3) + INT(0 + (P(Who%%).Age - 25)) * (.4 + ((P(Who%%).Age - 17) / 50) + .49)
  1127.  P(Who%%).Max_HP = P(Who%%).Max_HP + INT(RND * 10 - (P(Who%%).Age / 10)) + 1
  1128.  P(Who%%).Max_MP = P(Who%%).Max_MP + INT(RND * 5 + (P(Who%%).Age / 10))
  1129.  
  1130.  
  1131.  
  1132. FUNCTION Player_Battle_Defense~%% (who%%)
  1133.  'compute primary Defense value
  1134.  Result~%% = Player_Defense(who%%)
  1135.  'now check for luck bonus good or bad
  1136.  IF INT(RND * 255) <= (P(who%%).Luck \ 2) THEN 'if random chance is less than half player luck then give luck adjustment
  1137.   Result~%% = Result~%% + INT(RND * (P(who%%).Luck * 2) - (P(who%%).Luck - (P(who%%).Age * 2)))
  1138.  Player_Battle_Defense = Result~%%
  1139.  
  1140. FUNCTION Player_Defense~%% (who%%)
  1141.  'compute defense value to display in status window and to use in battle defense function
  1142.  Result~%% = INT(P(who%%).Agility / 2 - .49) + I(P(who%%).Armor).Power + I(P(who%%).Shield).Power
  1143.  Player_Defense = Result~%%
  1144.  
  1145. FUNCTION Player_Attack~%% (who%%)
  1146.  'Compute Attack value to display in status window and to use in battle attack function
  1147.  Result~%% = INT(P(who%%).Strength) + I(P(who%%).Weapon).Power
  1148.  Player_Attack = Result~%%
  1149.  
  1150. FUNCTION Player_Battle_Attack~%% (who%%)
  1151.  'get primary attack value
  1152.  Result~%% = Player_Attack(who%%)
  1153.  C~%% = Chance
  1154.  IF C~%% < (P(who%%).Luck \ 2) THEN 'if random chance is less than half player luck then give luck adjustment
  1155.   Result~%% = Result~%% + INT(RND * (P(who%%).Luck * 2) - (P(who%%).Luck - (P(who%%).Age * 2)))
  1156.  ELSEIF C~%% >= (128 - P(who%%).Luck / 16) AND C~%% <= (128 + P(who%%).Luck / 16) THEN 'critical hit
  1157.   Result~%% = Result~%% + INT(Result~%% * .25) 'add 25% to hit value
  1158.  Player_Battle_Attack = Result~%%
  1159.  
  1160. FUNCTION Enemy_Damage (ID%%, Who%%)
  1161.  IF Player_Battle_Defense(Who%%) / 2 > M(ID%%).Strength THEN Miss%% = INT(M(ID%%).Strength + 4 / 6) ELSE Miss%% = FALSE
  1162.  Low~%% = (M(ID%%).Strength - Player_Battle_Defense(Who%%) / 2) / 4
  1163.  High~%% = (M(ID%%).Strength - Player_Battle_Defense(Who%%) / 2) / 2
  1164.  
  1165.  IF (Chance < P(Who%%).Luck / 4) THEN 'player evades attack(-1)
  1166.   Result%% = TRUE
  1167.  ELSEIF Miss%% >= 0 THEN 'not really a miss just a weak hit
  1168.   Result%% = Miss%%
  1169.  ELSE 'normal attack damage
  1170.   Result%% = INT(RND * (High~%% - Low~%%)) + Low~%%
  1171.  
  1172. FUNCTION Player_Damage (who%%, ID%%)
  1173.  IF Chance + P(who%%).Luck / 2 > 228 THEN 'critical hit
  1174.   Low~%% = (Player_Battle_Attack(who%%) / 2)
  1175.   High~%% = (Player_Battle_Attack(who%%))
  1176.   Low~%% = (Player_Battle_Attack(who%%) - M(ID%%).Agility / 2) / 4
  1177.   High~%% = (Player_Battle_Attack(who%%) - M(ID%%).Agility / 2) / 2
  1178.  Result~%% = INT(RND * (High~%% - Low~%%)) + Low~%%
  1179.  IF Result~%% = 0 THEN
  1180.   IF Chance + (P(who%%).Luck / 2) > 127 THEN Result~%% = 1
  1181.  Player_Damage = Result~%%
  1182.  
  1183. FUNCTION Enemy_Flee (ID%%, Who%%)
  1184.  IF Player_Attack(Who%%) >= M(ID%%).Strength * 2 THEN
  1185.   IF Chance > 192 THEN Result%% = TRUE ELSE Result%% = FALSE
  1186.  Enemy_Flee = Result%%
  1187.  
  1188. FUNCTION Player_Flee (Who%%, Id%%)
  1189.  IF P(Who%%).Agility * Chance < M(Id%%).Agility * Chance * GF(M(Id%%).Group) THEN
  1190.   Result%% = FALSE 'player is blocked
  1191.   Result%% = TRUE 'player evades
  1192.  Player_Flee = Result%%
  1193.  
  1194. FUNCTION Battle_Initiative (who%%, ID%%)
  1195.  'if false then enemy goes first else player goes first in battle
  1196.  IF P(who%%).Agility * Chance < M(ID%%).Agility * Chance * GF(1) THEN
  1197.   Result%% = FALSE 'Monster goes first
  1198.   Result%% = TRUE 'player Goes first
  1199.  Battle_Initiative = Result%%
  1200.  
  1201. FUNCTION Chance~%%
  1202.  Chance = INT(RND * 255)
  1203.  
  1204.  
  1205. 'Debugging stuff found below---------------------------------------------------
  1206. SUB Print_Inventory (who%%)
  1207.  'check that values in inventory are correct
  1208.  'DEBUGGING!_-------------------------------
  1209.  STATIC m AS _MEM 'no need to initialize/free it over and over
  1210.  m = _MEM(P(who%%)) 'Just change where you want to point it to.
  1211.  Pack = m.OFFSET + 28 '‘move to where P(Who%%).Pack starts at in memory
  1212.  LOCATE 1, 1
  1213.  FOR i%% = 0 TO P(who%%).Items - 1
  1214.   PRINT "Item ID#:"; I(_MEMGET(m, Pack + 2 * i%%, _BYTE)).Nam
  1215.   PRINT "Item Count:"; _MEMGET(m, Pack + 2 * i%% + 1, _BYTE)
  1216.  NEXT i%%
  1217.  
  1218. SUB Debuginfo
  1219.  IF P(who%%).Map >= 0 THEN
  1220.   _PRINTSTRING (528, 8), "Tile :" + STR$(Place(P(who%%).Map, P(who%%).MapX, P(who%%).MapY).Sprite_ID) + "  ", Layer(9)
  1221.   _PRINTSTRING (528, 24), "Map X:" + STR$(P(who%%).MapX) + "  ", Layer(9)
  1222.   _PRINTSTRING (528, 40), "Map Y:" + STR$(P(who%%).MapY) + "  ", Layer(9)
  1223.   _PRINTSTRING (528, 56), "ExitBlock:" + STR$(Place(P(who%%).Map, P(who%%).MapX, P(who%%).MapY).Is_Exit) + "  ", Layer(9)
  1224.   _PRINTSTRING (528, 168), "Stairs:" + STR$(Place(P(who%%).Map, P(who%%).MapX, P(who%%).MapY).Is_Stairs) + "  ", Layer(9)
  1225.   _PRINTSTRING (528, 72), "Tile   :" + STR$(World(P(who%%).WorldX, P(who%%).WorldY).Sprite_ID) + "  ", Layer(9)
  1226.   _PRINTSTRING (528, 88), "World X:" + STR$(P(who%%).WorldX) + "  ", Layer(9)
  1227.   _PRINTSTRING (528, 104), "World Y:" + STR$(P(who%%).WorldY) + "  ", Layer(9)
  1228.   _PRINTSTRING (528, 168), "Stairs:" + STR$(World(P(who%%).WorldX, P(who%%).WorldY).Is_Stairs) + "  ", Layer(9)
  1229.  _PRINTSTRING (528, 120), "Map ID:" + STR$(P(who%%).Map) + "  ", Layer(9)
  1230.  _PRINTSTRING (528, 136), "justleft:" + STR$(G.JustLeft) + "  ", Layer(9)
  1231.  _PRINTSTRING (528, 152), "message" + STR$(G.Message) + "  ", Layer(9)
  1232.  _PRINTSTRING (528, 184), "action:" + STR$(G.Action) + "  ", Layer(9)
  1233.  _PRINTSTRING (528, 200), "Command:" + STR$(G.Selection) + "  ", Layer(9)
  1234.  _PRINTSTRING (528, 216), "BGMusic:" + STR$(G.Current_BGM) + "  ", Layer(9)
  1235.  _PRINTSTRING (528, 232), "FPS:" + STR$(G.f) + "  ", Layer(9)
  1236.  _PRINTSTRING (528, 248), "NPC:" + STR$(Find_NPC(P(0).Facing)) + "  ", Layer(9)
  1237.  

Updated: 10\20\2019 14:50UTC
Updated: 10\23\2019 05:07UTC
Updated: 10\27\2019 18:27UTC
* DragonW.MFI (Filesize: 1.54 MB, Downloads: 125)
« Last Edit: October 27, 2019, 02:53:58 pm by Cobalt »
Granted after becoming radioactive I only have a half-life!

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Explore a world, visit ghost towns
« Reply #1 on: October 16, 2019, 08:06:24 pm »
Nicely done Cobalt - do enough people compliment your style? Killin the game, muh man... Keep it up.
You're not done when it works, you're done when it's right.

FellippeHeitor

  • Guest
Re: Explore a world, visit ghost towns
« Reply #2 on: October 16, 2019, 11:44:19 pm »
Great job, Cobalt! Very interesting engine!

Our user roadbloc (or maybe user pforpond, are you that?) is gonna have a blast, as she has done something very similar with her Mystery of Robot Planet.

Kudos! When's the making of video coming out?

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: Explore a world, visit ghost towns
« Reply #3 on: October 17, 2019, 12:26:54 pm »
Wow! Nice graphics. I like it!
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Explore a world, visit ghost towns
« Reply #4 on: October 17, 2019, 01:29:27 pm »
When's the making of video coming out?

I would hate to even imagine just how that would go!

I guess I could go over why I use the Layer() system I do, or how I get away with never needing an EXIT or GOTO statement to get things done in a program like this.

Beyond that I wouldn't even know where to start. :(
Granted after becoming radioactive I only have a half-life!

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Explore a world, visit ghost towns
« Reply #5 on: October 17, 2019, 05:09:25 pm »
Hi Cobalt
It is cool!
Lovely music, graphic and movement of sprites...

about to make video here some tips and software
https://www.techradar.com/news/the-best-free-screen-recorder
Programming isn't difficult, only it's  consuming time and coffee

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Explore a world, visit ghost towns
« Reply #6 on: October 20, 2019, 11:02:15 am »
Updated, fixed Message Handler for command window, added the STATUS functionality for command window. 

Added Loin Cloth sprite. Technically you start the game naked!, as you have to buy Cloths!

Always got a laugh out of that growing up. there was already sprites for when you don't have a weapon or shield.

It looks a little goofy but I was actually going for that, try to inspire the player to buy armor! but I guess you could play for a while with out armor, though even at the highest strength level a player wouldn't be able to beat mid-level creatures without armor.  and the higher the XP level the more AGE starts to act against attack and defense.

Don't forget you'll need to update your MFI file as it has been rebuilt to accommodate new Sound Effects.
« Last Edit: October 23, 2019, 11:50:47 am by Cobalt »
Granted after becoming radioactive I only have a half-life!

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Explore a world, visit ghost towns
« Reply #7 on: October 23, 2019, 01:15:21 pm »
There are now some NPCs to watch walk around, the Background music changes from castle, towns, and overworld. no music for caves\temples and such yet.

Starting castle is the only location with NPCs at the moment, and they are still mute. added a little frame rate clock, to see how far below 60 it will drop, should never go below 60 for smooth play.

MFI file has been updated again.
Granted after becoming radioactive I only have a half-life!

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Explore the world of Alefgard! and talk to some people!
« Reply #8 on: October 27, 2019, 02:31:54 pm »
All towns(that should) have NPCs now!, the NPCs in the Castle now have basic talking ability! Everybody else should just be 'speechless'

Don't Forget to (re)download the MFI file.
« Last Edit: October 27, 2019, 02:54:31 pm by Cobalt »
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Explore the world of Alefgard! and talk to some people!
« Reply #9 on: October 27, 2019, 03:30:39 pm »
Wow talking! I assume this doesn't mean little bubbles of text above characters? well... even if it were, cool!

Please, what is NPC?

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Explore the world of Alefgard! and talk to some people!
« Reply #10 on: October 27, 2019, 03:36:09 pm »
Wow talking! I assume this doesn't mean little bubbles of text above characters? well... even if it were, cool!

Please, what is NPC?

Non-Player Character.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Explore the world of Alefgard! and talk to some people!
« Reply #11 on: October 28, 2019, 01:24:44 am »
Seems like the King is about to make a speech but nothing happens, also I have to use arrow keys up and down in Command Menu box to get a talk box, just Enter wont work, is that the way it is?

 
Descendent of Erdrick.PNG
« Last Edit: October 28, 2019, 01:26:11 am by bplus »

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Explore the world of Alefgard! and talk to some people!
« Reply #12 on: October 28, 2019, 11:52:49 am »
Seems like the King is about to make a speech but nothing happens, also I have to use arrow keys up and down in Command Menu box to get a talk box, just Enter wont work, is that the way it is?

The King has the most lines of anyone, but the Monologue system is proving arduous, at best, to figure out. Many NPCs(Non-Playable Characters, Steve was close) have multiple lines, and there should be a pause requiring a button(key in this case) press to move on, and others have a Yes\No option as well. The Completion of this program will hang on this unfortunately. Until then every NPC only speaks the first line of their script. and you can't speak to any shop keeps due to the tile in front of them, yet another hurtle to figure out. All the NPCs that say they are speechless don't have a DATA line yet, and just say that as default.

Space is the "action" button(key), or  button A if we were using an old NES controller, while "enter" is the cancel or the B button. I know its a little counter-intuitive and I honestly can't remember why I came to that setup. Eventually the Controls will be customize-able though. so Space to bring up the command window, Space to choose an option. I'm afraid it is a short coming on my part to assume the player has some knowledge of the NES version of the game before hand, and knows which button (A or B) to use.

something that intrigues me about your screen shot is the 61FPS, as with the _LIMIT 60 that should not be able to happen, I thought. and that could actually cause some glitches with the movement and drawing of the screen. Which is why I'm taking the speed of this program more serious than others I have done. there are slight dips when changing maps which should be okay at that point once I finish that aspect, as the maps should fade out and in.
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Explore the world of Alefgard! and talk to some people!
« Reply #13 on: October 28, 2019, 12:08:16 pm »
Thanks, OK.

I must compliment the smooth walk-around aspect of players movements, it seems even better than my little experiment demo in effort to help.

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Explore the world of Alefgard! and talk to some people!
« Reply #14 on: October 29, 2019, 02:03:39 pm »
Cobalt this is really incredible. It reminds me of my days playing Legend of Zelda and other games. You are coming along on it great! I can't wait to see the final version to fight enemies and get weapons and gold. I walked around in almost the whole forest and went to that other town. I never knew such a cool game like this could be made with a BASIC language!