1Option Explicit
2
3Dim oCurrentLayer, oPlayerSprite, nCurX, nCurY
4Dim nTLTile, nTRTile, nBLTile, nBRTile, nCTile, nCBelow, nBLBTile, nBRBTile
5Dim nTileBelow, oLadderGroup, oStopFallGroup, oBarGroup, nTopOftile
6Dim oWalkSolidGroup, oHoleAnim, oClimbSolidGroup
7Dim oWalkDef, oLadderDef, oFallDef, oHangDef, oDrillDef
8
9Dim oEnemyPathData
10Dim nIteration ' 0 = A, 4 = B
11Public Const nQueueBufSize = 4096
12Dim arSearchQueue(4095)
13Dim nQueueStart
14Dim nQueueSize
15Dim oEnemyTemplate
16
17Public Const TileSize = 32
18Public Const TileSizeMinus1 = 31
19Public Const HalfTileSize = 16
20
21' Long Integer Array
22' Low byte = X tile
23' Next byte = Y tile
24' Next byte = Current Delay
25' High byte = Current Frame
26Public Const nHoleBufSize = 64
27Dim Holes(63)
28Dim nHoleCount
29Dim nFirstHole
30
31Dim DefaultMapData
32
33Sub Player_OnAfterMoveSprites()
34Dim I, oSprite
35
36If IsEmpty(oPlayerSprite) Then Exit Sub
37ProcessPlayerMovement
38ProcessHoles
39SearchStep 2, False
40If (nQueueStart > 10) Then SearchStep 1, True
41
42For I = 0 To oCurrentLayer.SpriteCount - 1
43Set oSprite = oCurrentLayer.Sprite(I)
44If oSprite.rDef.Template Is oEnemyTemplate Then
45ProcessEnemy oSprite
46oSprite.CurFrame = oSprite.CurFrame Mod oSprite.rDef.Template.StateFrameCount(oSprite.CurState)
47End If
48Next
49
50End Sub
51
52Sub CheckEnemyCrushed()
53Dim I
54For I = 0 To oCurrentLayer.SpriteCount - 1
55With oCurrentLayer.Sprite(I)
56If .rDef.Template Is oEnemyTemplate Then
57If oClimbSolidGroup.IsMember(oCurrentLayer.Data.TileValue( _
58(.X + HalfTileSize) \ TileSize, (.Y + TileSizeMinus1) \ TileSize)) Then
59.X = .rDef.rPath.PointX(0)
60.Y = .rDef.rPath.PointY(0)
61.CurState = 6
62.DX = 0
63.DY = 0
64.CurFrame = 0
65End If
66End If
67End With
68Next
69End Sub
70
71Sub Player_OnTileInteraction(X, Y, Tile, bNew, nIdx)
72If ProjectObj.GamePlayer.InvQuantityOwned(0) = ProjectObj.GamePlayer.InvMaxQuantity(0) Then
73oCurrentLayer.Data.TileMapping(45)=11
74End If
75End Sub
76
77Sub PlayerDie()
78Dim I
79
80oCurrentLayer.Data.MapData = DefaultMapData
81ProjectObj.GamePlayer.InvQuantityOwned(0) = 0
82oCurrentLayer.Data.TileMapping(45) = 0
83
84For I = 0 To oCurrentLayer.SpriteCount - 1
85With oCurrentLayer.Sprite(I)
86.X = .rDef.rPath.PointX(0)
87.Y = .rDef.rPath.PointY(0)
88.CurState = 0
89.CurFrame = 0
90.DX = 0
91.DY = 0
92.UserData = Empty
93End With
94Next
95ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Walk")
96Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
97
98nHoleCount=0
99End Sub
100
101Sub Player_OnSpritesCollide(Name, ClassAIdx, ClassBIdx, CollDefIdx)
102PlayerDie
103End Sub
104
105Sub ProcessHoles()
106Dim nCurHole, nAfterEndHole
107Dim nTileX, nTileY
108Dim nFrame, nDelay
109Dim nHoleVal
110
111nAfterEndHole = (nFirstHole + nHoleCount) Mod nHoleBufSize
112If ProjectObj.GamePlayer.CtlActions And ACTION_BUTTON2 Then
113' Drill hole to the left
114nTileX = CLng((nCurX + HalfTileSize) \ TileSize - 1)
115nTileY = CLng(nCurY \ TileSize + 1)
116If nHoleCount < nHoleBufSize And nTileX >= 0 And nTileY < oCurrentLayer.Rows Then
117If oCurrentLayer.Data.TileValue(nTileX, nTileY) = oWalkSolidGroup.GetMember(0) And _
118Not oStopFallGroup.IsMember(oCurrentLayer.Data.TileValue(nTileX, nTileY-1)) Then
119nHoleCount = nHoleCount + 1
120Holes(nAfterEndHole) = CLng(nTileX) + CLng(nTileY) * CLng(256)
121oCurrentLayer.Data.TileValue(nTileX, nTileY) = oHoleAnim.FrameValue(0)
122nAfterEndHole = (nFirstHole + nHoleCount) Mod nHoleBufSize
123ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Drill")
124Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
125oPlayerSprite.CurState = 0
126End If
127End If
128End If
129If ProjectObj.GamePlayer.CtlActions And ACTION_BUTTON3 Then
130' Drill hole to the Right
131nTileX = CLng((nCurX + HalfTileSize) \ TileSize + 1)
132nTileY = CLng(nCurY \ TileSize + 1)
133If nHoleCount < nHoleBufSize And nTileX < oCurrentLayer.Columns And nTileY < oCurrentLayer.Rows Then
134If oCurrentLayer.Data.TileValue(nTileX, nTileY) = oWalkSolidGroup.GetMember(0) And _
135Not oStopFallGroup.IsMember(oCurrentLayer.Data.TileValue(nTileX, nTileY-1)) Then
136nHoleCount = nHoleCount + 1
137Holes(nAfterEndHole) = nTileX + nTileY * &H100&
138oCurrentLayer.Data.TileValue(nTileX, nTileY) = oHoleAnim.FrameValue(0)
139nAfterEndHole = (nFirstHole + nHoleCount) Mod nHoleBufSize
140ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Drill")
141Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
142oPlayerSprite.CurState = 1
143End If
144End If
145End If
146
147nCurHole = nFirstHole
148Do While nCurHole <> nAfterEndHole
149nHoleVal = Holes(nCurHole)
150nTileX = CLng(nHoleVal Mod &H100&)
151nTileY = CLng((nHoleVal And &HFF00&) \ &H100&)
152nDelay = CLng((nHoleVal And &HFF0000&) \ &H10000&)
153nFrame = CLng((nHoleVal And &H7F000000&) \ &H1000000&)
154If nDelay >= oHoleAnim.FrameDelay(nFrame) Then
155nFrame = nFrame + 1
156nDelay=1
157If nFrame >= oHoleAnim.FrameCount Then
158nFirstHole = (nFirstHole + 1) Mod nHoleBufSize
159nHoleCount = nHoleCount - 1
160oCurrentLayer.Data.TileValue(nTileX, nTileY) = oWalkSolidGroup.GetMember(0)
161Else
162oCurrentLayer.Data.TileValue(nTileX, nTileY) = oHoleAnim.FrameValue(nFrame)
163End If
164CheckEnemyCrushed
165Else
166nDelay = nDelay + 1
167End If
168Holes(nCurHole) = nTileX + nTileY * &H100 + nDelay * &H10000 + nFrame * &H1000000
169nCurHole = (nCurHole + 1) Mod nHoleBufSize
170Loop
171End Sub
172
173Sub ProcessPlayerMovement()
174
175If ProjectObj.GamePlayer.CtlActions And ACTION_BUTTON4 Then
176PlayerDie
177Exit Sub
178End If
179
180nCurX = Int(oPlayerSprite.X)
181nCurY = Int(oPlayerSprite.Y)
182nTLTile = oCurrentLayer.Data.TileValue(nCurX \ TileSize, nCurY \ TileSize)
183If nCurX Mod TileSize = 0 Then nTRTile = nTLTile Else nTRTile = oCurrentLayer.Data.TileValue((nCurX+TileSizeMinus1) \ TileSize, nCurY \ TileSize)
184If nCurY Mod TileSize = 0 Then nBLTile = nTLTile Else nBLTile = oCurrentLayer.Data.TileValue(nCurX \ TileSize, (nCurY+TileSizeMinus1) \ TileSize)
185If nCurY Mod TileSize = 0 Then
186nBRTile = nTRTile
187ElseIf nCurX Mod TileSize = 0 Then
188nBRTile = nBLTile
189Else
190nBRTile = oCurrentLayer.Data.TileValue((nCurX+TileSizeMinus1) \ TileSize, (nCurY+TileSizeMinus1) \ TileSize)
191End If
192If nCurY \ TileSize + 1 < oCurrentLayer.Rows Then
193If nCurY Mod TileSize > 0 Then
194nBLBTile = nBLTile
195nBRBTile = nBRTile
196Else
197nBLBTile = oCurrentLayer.Data.TileValue(nCurX \ TileSize, nCurY \ TileSize + 1)
198nBRBTile = oCurrentLayer.Data.TileValue((nCurX+TileSizeMinus1) \ TileSize, nCurY \ TileSize + 1)
199End If
200If nCurX Mod TileSize >= HalfTileSize Then nCBelow = nBRBTile Else nCBelow = nBLBTile
201Else
202nBLBTile = 46
203nBRBTile = 46
204nCBelow = 46
205End If
206
207If nCurX Mod TileSize >= HalfTileSize Then
208If nCurY Mod TileSize >= HalfTileSize Then nCTile = nBRTile Else nCTile = nTRTile
209Else
210If nCurY Mod TileSize >= HalfTileSize Then nCTile = nBLTile Else nCTile = nTLTile
211End If
212
213nTopOfTile = (nCurY\TileSize) * TileSize
214
215If oClimbSolidGroup.IsMember(nBLTile) Or oClimbSolidGroup.IsMember(nBRTile) Then
216PlayerDie
217End If
218
219If oPlayerSprite.rDef Is oLadderDef Then
220If Not (oLadderGroup.IsMember(nBRTile) Or oLadderGroup.IsMember(nBLTile) Or _
221oLadderGroup.IsMember(nTRTile) Or oLadderGroup.IsMember(nTLTile)) Then
222If Not CheckHangAndLadder Then
223If Not (oStopFallGroup.IsMember(nBLBTile) Or oStopFallGroup.IsMember(nBRBTile)) Then
224ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Fall")
225Else
226ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Walk")
227End If
228Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
229End If
230Else
231If ((ProjectObj.GamePlayer.CtlActions And ACTION_UP) > 0) Or _
232((ProjectObj.GamePlayer.CtlActions And ACTION_DOWN) > 0) Then
233oPlayerSprite.X = ((oPlayerSprite.X+HalfTileSize) \ TileSize) * TileSize
234oPlayerSprite.DX = 0
235ElseIf oPlayerSprite.DX <> 0 Then
236oPlayerSprite.DY = 0
237End If
238End If
239ElseIf oPlayerSprite.rDef is oWalkDef Then
240If Not (oStopFallGroup.IsMember(nBLBTile) Or oStopFallGroup.IsMember(nBRBTile)) Then
241If Not CheckHangAndLadder Then
242oPlayerSprite.X = nCurX - oPlayerSprite.DX
243ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Fall")
244Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
245oPlayerSprite.X = ((oPlayerSprite.X+HalfTileSize) \ TileSize) * TileSize
246oPlayerSprite.DY = 1
247End If
248ElseIf oBarGroup.IsMember(nCTile) Then
249ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Hang")
250Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
251oPlayerSprite.Y = nTopOfTile
252oPlayerSprite.DY = 0
253ElseIf ((ProjectObj.GamePlayer.CtlActions And ACTION_UP) > 0) And _
254oLadderGroup.IsMember(nCTile) Then
255ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("ClimbLadder")
256Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
257oPlayerSprite.X = ((oPlayerSprite.X+HalfTileSize) \ TileSize) * TileSize
258ElseIf (ProjectObj.GamePlayer.CtlActions And ACTION_DOWN) > 0 And _
259oLadderGroup.IsMember(nCBelow) Then
260ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("ClimbLadder")
261Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
262oPlayerSprite.X = ((oPlayerSprite.X+HalfTileSize) \ TileSize) * TileSize
263ElseIf oLadderGroup.IsMember(nBLBTile) Or oLadderGroup.IsMember(nBRBTile) Then
264oPlayerSprite.Y = nTopOfTile
265oPlayerSprite.DY = 0
266End If
267ElseIf oPlayerSprite.rDef Is oFallDef Then
268If oPlayerSprite.DY <=0 Then
269ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Walk")
270Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
271Else
272CheckHangAndLadder
273End If
274ElseIf oPlayerSprite.rDef Is oHangDef Then
275If nCurY <> nTopOfTile Or Not (oBarGroup.IsMember(nTLTile) Or oBarGroup.IsMember(nTRTile)) Then
276If Not CheckHangAndLadder Then
277ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Fall")
278Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
279oPlayerSprite.DY = 1
280End If
281ElseIf (ProjectObj.GamePlayer.CtlActions And ACTION_DOWN) > 0 Then
282ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Fall")
283Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
284oPlayerSprite.DY = 1
285End If
286ElseIf oPlayerSprite.rDef Is oDrillDef Then
287If (ProjectObj.GamePlayer.CtlActions And (ACTION_LEFT Or ACTION_RIGHT Or _
288ACTION_UP Or ACTION_DOWN)) Or oPlayerSprite.DY > 0 Then
289ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Walk")
290Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
291End If
292End If
293End Sub
294
295Public Function CheckHangAndLadder()
296If nCurY = nTopOfTile And _
297(oBarGroup.IsMember(nTLTile) Or oBarGroup.IsMember(nTRTile)) Then
298ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("Hang")
299Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
300oPlayerSprite.DY = 0
301CheckHangAndLadder = True
302Exit Function
303ElseIf oLadderGroup.IsMember(nTLTile) Or oLadderGroup.IsMember(nTRTile) Or _
304oLadderGroup.IsMember(nBLTile) Or oLadderGroup.IsMember(nBRTile) Then
305ProjectObj.GamePlayer.ActivateFunction ProjectObj.GamePlayer.rMap.Specials("ClimbLadder")
306Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
307CheckHangAndLadder = True
308Exit Function
309End If
310
311CheckHangAndLadder = False
312End Function
313
314Sub PlayerSeedSearch()
315nQueueStart = 0
316nQueueSize = 1
317arSearchQueue(0) = (nCurX+HalfTileSize) \ TileSize + ((nCurY+HalfTileSize) \ TileSize) * 128
318nIteration = nIteration Xor 4
319End Sub
320
321Sub InitSearch()
322Dim nX, nY
323Dim nRows, nCols
324Dim nPTile, nPTileAboveThat
325
326oCurrentLayer.pMap.AddLayer "EnemySearch", "tsSearch", 1, 1, True
327Set oEnemyPathData = oCurrentLayer.pMap.MapLayer("EnemySearch").Data
328oCurrentLayer.pMap.MapLayer("EnemySearch").LoadTiles(CurrentDisplay)
329oCurrentLayer.pMap.RemoveLayer("EnemySearch")
330nQueueStart = 0
331nQueueSize = 0
332
333nRows = oCurrentLayer.Rows
334nCols = oCurrentLayer.Columns
335
336For nY = 1 To nRows - 1
337For nX = 0 To nCols - 1
338oEnemyPathData.TileValue(nX,nY) = 0
339If Not oStopFallGroup.IsMember(oCurrentLayer.Data.TileValue(nX, nY)) Then
340nPTile = oCurrentLayer.Data.TileValue(nX, nY-1)
341If oLadderGroup.IsMember(nPTile) Or oBarGroup.IsMember(nPTile) Then
342oEnemyPathData.TileValue(nX,nY) = 8
343ElseIf oEnemyPathData.TileValue(nX, nY-1) And 8 Then
344oEnemyPathData.TileValue(nX,nY) = 8
345ElseIf Not oWalkSolidGroup.IsMember(nPTile) Then
346If nX > 0 Then
347nPTile = oCurrentLayer.Data.TileValue(nX-1, nY)
348nPTileAboveThat = oCurrentLayer.Data.TileValue(nX-1, nY-1)
349If oBarGroup.IsMember(nPTileAboveThat) Or oStopFallGroup.IsMember(nPTile) And _
350Not oWalkSolidGroup.IsMember(nPTileAboveThat) Then
351oEnemyPathData.TileValue(nX, nY) = 8
352End If
353End If
354If nX < oCurrentLayer.Columns - 1 Then
355nPTile = oCurrentLayer.Data.TileValue(nX+1, nY)
356nPTileAboveThat = oCurrentLayer.Data.TileValue(nX+1, nY-1)
357If oBarGroup.IsMember(nPTileAboveThat) Or oStopFallGroup.IsMember(nPTile) And _
358Not oWalkSolidGroup.IsMember(nPTileAboveThat) Then
359oEnemyPathData.TileValue(nX, nY) = 8
360End If
361End If
362End If
363End If
364Next
365Next
366End Sub
367
368Sub InitMap(oMap)
369Dim nX, nY
370Dim oNewPath, oNewSprite
371Dim nTile
372Dim nEnemyNum
373Dim oCacheEnemyTemplate
374Dim oEditLayer
375Dim I
376Dim nPlayerX, nPlayerY
377
378For I = 0 To ProjectObj.Maps("Intro").SpriteTemplateCount - 1
379oMap.AddSpriteTemplate ProjectObj.Maps("Intro").SpriteTemplates(I).Clone
380Next
381
382For I = 0 To oMap.SpriteTemplateCount - 1
383If Instr(oMap.SpriteTemplates(I).Name, "Enemy") Then Exit For
384Next
385
386If I < oMap.SpriteTemplateCount Then Set oCacheEnemyTemplate = oMap.SpriteTemplates(I)
387
388Set oEditLayer = oMap.MapLayer(0)
389ProjectObj.GamePlayer.InvMaxQuantity(0) = 0
390
391oMap.AddLayer "Foreground", "tsMain", 1, 1, True
392
393For nY = 0 To oEditLayer.Rows - 1
394For nX = 0 To oEditLayer.Columns - 1
395Select Case oEditLayer.Data.TileValue(nX, nY)
396Case 1,2,3,4,5,6,7,8,9
397nPlayerX = nX
398nPlayerY = nY
399oEditLayer.Data.TileValue(nX, nY) = 0
400Case 20,21,22,23,24,25,26,27,28
401Set oNewPath = NewPath
402oNewPath.AddPoint nX * TileSize, nY * TileSize
403oNewPath.LayerName = oEditLayer.Name
404nEnemyNum = nEnemyNum + 1
405oNewPath.Name = "Enemy" & nEnemyNum & "Path"
406oMap.AddPath HostObj.AsObject(oNewPath)
407Set oNewSprite = NewSpriteDef
408oNewSprite.Flags = FLAG_INSTANCE
409oNewSprite.Name = "Enemy" & nEnemyNum
410Set oNewSprite.rPath = oNewPath
411Set oNewSprite.rLayer = oEditLayer
412Set oNewSprite.Template = oCacheEnemyTemplate
413oMap.AddSpriteDef HostObj.AsObject(oNewSprite)
414oEditLayer.Data.TileValue(nX, nY) = 0
415Case 15, 16, 17, 18, 19
416ProjectObj.GamePlayer.InvMaxQuantity(0) = _
417ProjectObj.GamePlayer.InvMaxQuantity(0) + 1
418oEditLayer.Data.TileValue(nX, nY) = 15
419Case 12
420oMap.MapLayer("Foreground").Data.TileValue(nX, nY) = 13
421End Select
422Next
423Next
424
425Set oNewPath = NewPath
426oNewPath.AddPoint nPlayerX * TileSize, nPlayerY * TileSize
427oNewPath.LayerName = oEditLayer.Name
428oNewPath.Name = "PlayerPath"
429oMap.AddPath HostObj.AsObject(oNewPath)
430Set oFallDef = NewSpriteDef
431oFallDef.Flags = FLAG_INSTANCE
432oFallDef.Name = "PlayerFall"
433Set oFallDef.rPath = oNewPath
434Set oFallDef.rLayer = oEditLayer
435Set oFallDef.Template = oMap.SpriteTemplates("PlayerFall")
436oMap.AddSpriteDef HostObj.AsObject(oFallDef)
437
438Set oWalkDef = NewSpriteDef
439oWalkDef.Name = "PlayerWalk"
440Set oWalkDef.rPath = oNewPath
441Set oWalkDef.rLayer = oEditLayer
442Set oWalkDef.Template = oMap.SpriteTemplates("PlayerWalk")
443oMap.AddSpriteDef HostObj.AsObject(oWalkDef)
444
445Set oLadderDef = NewSpriteDef
446oLadderDef.Name = "PlayerLadder"
447Set oLadderDef.rPath = oNewPath
448Set oLadderDef.rLayer = oEditLayer
449Set oLadderDef.Template = oMap.SpriteTemplates("PlayerLadder")
450oMap.AddSpriteDef HostObj.AsObject(oLadderDef)
451
452Set oHangDef = NewSpriteDef
453oHangDef.Name = "PlayerHang"
454Set oHangDef.rPath = oNewPath
455Set oHangDef.rLayer = oEditLayer
456Set oHangDef.Template = oMap.SpriteTemplates("PlayerHang")
457oMap.AddSpriteDef HostObj.AsObject(oHangDef)
458
459Set oDrillDef = NewSpriteDef
460oDrillDef.Name = "PlayerDrill"
461Set oDrillDef.rPath = oNewPath
462Set oDrillDef.rLayer = oEditLayer
463Set oDrillDef.Template = oMap.SpriteTemplates("PlayerDrill")
464oMap.AddSpriteDef HostObj.AsObject(oDrillDef)
465
466oMap.PlayerSpriteName = "PlayerFall"
467
468AddSwitchFunc True, "Walk", "PlayerWalk", oMap
469AddSwitchFunc True, "Hang", "PlayerHang", oMap
470AddSwitchFunc False, "Drill", "PlayerDrill", oMap
471AddSwitchFunc False, "ClimbLadder", "PlayerLadder", oMap
472AddSwitchFunc False, "Fall", "PlayerFall", oMap
473AddEndFunc oMap
474
475Dim oNewCollDef
476Set oNewCollDef = NewCollisionDef
477oNewCollDef.ClassA = 0 ' Player
478oNewCollDef.ClassB = 1 ' Enemy
479oMap.AddCollDef HostObj.AsObject(oNewCollDef)
480
481oMap.AddInteraction ProjectObj.Maps("Intro").Interactions(0)
482End Sub
483
484Sub AddSwitchFunc(bRetainState, Name, DefName, oMap)
485Dim oNewSpecial
486
487Set oNewSpecial = NewSpecialFunction
488If bRetainState Then
489oNewSpecial.Flags = INTFL_NEWINSTANCE Or INTFL_DELETEOLD Or _
490INTFL_OLDLOCATION Or INTFL_RETAINSTATE
491Else
492oNewSpecial.Flags = INTFL_NEWINSTANCE Or INTFL_DELETEOLD Or INTFL_OLDLOCATION
493End If
494oNewSpecial.FuncType = SPECIAL_SWITCHSPRITE
495oNewSpecial.LayerIndex = 0
496oNewSpecial.Name = Name
497oNewSpecial.SpriteName = DefName
498oNewSpecial.TileLeft = -1
499oNewSpecial.TileTop = -1
500oNewSpecial.TileBottom = -1
501oNewSpecial.TileRight = -1
502oMap.AddSpecial HostObj.AsObject(oNewSpecial)
503End Sub
504
505Sub AddEndFunc(oMap)
506Dim oNewSpecial
507
508Set oNewSpecial = NewSpecialFunction
509oNewSpecial.Flags = INTFL_RAISEEVENT
510oNewSpecial.FuncType = SPECIAL_EVENT
511oNewSpecial.LayerIndex = 0
512oNewSpecial.Name = oMap.Name & "Finish"
513oNewSpecial.TileLeft = 0
514oNewSpecial.TileTop = 0
515oNewSpecial.TileBottom = 0
516oNewSpecial.TileRight = oMap.MapLayer(0).Columns-1
517oMap.AddSpecial HostObj.AsObject(oNewSpecial)
518End Sub
519
520Sub Player_OnSpecialFunction(Func)
521Dim oNextMap
522Dim I
523
524If ProjectObj.GamePlayer.InvQuantityOwned(0) <> _
525ProjectObj.GamePlayer.InvMaxQuantity(0) Then Exit Sub
526
527Select Case left(ProjectObj.GamePlayer.rMap.Name,3)
528Case "Int"
529Set oNextMap = ProjectObj.Maps("Map1")
530Case "Map"
531If CInt(Mid(ProjectObj.GamePlayer.rMap.Name,4)) < ProjectObj.MapCount-2 Then
532Set oNextMap = ProjectObj.Maps("Map" & CStr(CInt(Mid(ProjectObj.GamePlayer.rMap.Name,4))+1))
533Else
534Set oNextMap = ProjectObj.Maps("Finale")
535End If
536End Select
537
538ProjectObj.GamePlayer.InvQuantityOwned(0)=0
539
540If IsEmpty(oNextMap) Then Exit Sub
541
542If Not IsEmpty(oNextMap) Then
543InitMap oNextMap
544Set ProjectObj.GamePlayer.rMap.Disp = Nothing
545Set ProjectObj.GamePlayer.rMap = oNextMap
546With ProjectObj.AnimDefs("Gold")
547.MapName = oNextMap.Name
548.LayerName = oNextMap.MapLayer(0).Name
549End With
550With oNextMap
551Set .Disp = CurrentDisplay
552.LoadTiles
553.LoadTileAnims
554.InitSprites
555ProjectObj.GamePlayer.InitPlayerSprite
556End With
557End If
558
559Set oPlayerSprite = ProjectObj.GamePlayer.PlayerSprite
560Set oCurrentLayer = oPlayerSprite.rDef.rLayer
561Set oLadderGroup = ProjectObj.Groups("Ladder", "tsMain").Group
562Set oStopFallGroup = ProjectObj.Groups("StopFall", "tsMain").Group
563Set oBarGroup = ProjectObj.Groups("Bar", "tsMain").Group
564Set oWalkSolidGroup = ProjectObj.Groups("WalkSolid", "tsMain").Group
565Set oHoleAnim = ProjectObj.AnimDefs("Hole")
566Set oClimbSolidGroup = ProjectObj.Groups("ClimbSolid", "tsMain").Group
567
568InitSearch
569InitEnemies
570DefaultMapData = oCurrentLayer.Data.MapData
571oCurrentLayer.Data.TileMapping(45)=0
572End Sub
573
574Sub InitEnemies()
575Dim I
576Dim oEnemyTS
577
578For I = 0 To oCurrentLayer.pMap.SpriteTemplateCount - 1
579If Instr(oCurrentLayer.pMap.SpriteTemplates(I).Name, "Enemy") Then Exit For
580Next
581
582If I >= oCurrentLayer.pMap.SpriteTemplateCount Then Exit Sub
583
584Set oEnemyTemplate = oCurrentLayer.pMap.SpriteTemplates(I)
585Set oEnemyTS = oEnemyTemplate.StateTilesetDef(0)
586
587oEnemyTemplate.StateType = 99 ' Some Non-Standard type
588oEnemyTemplate.StateCount = 7
589' 0 = Walking Left
590' 1 = Walking Right
591' 2 = Climbing Up
592' 3 = Climbing Down
593' 4 = Swinging Left
594' 5 = Swinging Right
595' 6 = Falling
596
597oEnemyTemplate.ClearState 0
598oEnemyTemplate.ClearState 1
599oEnemyTemplate.ClearState 2
600oEnemyTemplate.ClearState 3
601oEnemyTemplate.ClearState 4
602oEnemyTemplate.ClearState 5
603oEnemyTemplate.ClearState 6
604
605Set oEnemyTemplate.StateTilesetDef(0) = oEnemyTS
606Set oEnemyTemplate.StateTilesetDef(1) = oEnemyTS
607Set oEnemyTemplate.StateTilesetDef(2) = oEnemyTS
608Set oEnemyTemplate.StateTilesetDef(3) = oEnemyTS
609Set oEnemyTemplate.StateTilesetDef(4) = oEnemyTS
610Set oEnemyTemplate.StateTilesetDef(5) = oEnemyTS
611Set oEnemyTemplate.StateTilesetDef(6) = oEnemyTS
612
613oEnemyTemplate.AppendStateFrame 0, 22
614oEnemyTemplate.AppendStateFrame 0, 23
615oEnemyTemplate.AppendStateFrame 1, 20
616oEnemyTemplate.AppendStateFrame 1, 21
617oEnemyTemplate.AppendStateFrame 2, 24
618oEnemyTemplate.AppendStateFrame 2, 25
619oEnemyTemplate.AppendStateFrame 3, 24
620oEnemyTemplate.AppendStateFrame 3, 25
621oEnemyTemplate.AppendStateFrame 4, 27
622oEnemyTemplate.AppendStateFrame 4, 28
623oEnemyTemplate.AppendStateFrame 5, 27
624oEnemyTemplate.AppendStateFrame 5, 28
625oEnemyTemplate.AppendStateFrame 6, 26
626End Sub
627
628Sub ProcessEnemy(oSprite)
629Dim nX, nY
630Dim nTileX, nTileY
631Dim nTile, nTileBelowRight, nTileBelowLeft
632Dim nTileLeftFoot, nTileRightFoot
633Dim nMapping
634
635If Not IsEmpty(oSprite.UserData) Then
636nX = oSprite.UserData
637nY = nX \ 128
638nX = nX Mod 128
639oCurrentLayer.Data.TileValue(nX, nY) = 0
640oSprite.UserData = Empty
641End If
642
643nX = Int(oSprite.X)
644nY = Int(oSprite.Y)
645
646nTileX = (nX + HalfTileSize) \ TileSize
647nTileY = (nY + HalfTileSize) \ TileSize
648nMapping = oCurrentLayer.Data.TileMapping(45)
649oCurrentLayer.Data.TileMapping(45) = 45
650nTile = oCurrentLayer.Data.TileValue(nTileX, nTileY)
651oCurrentLayer.Data.TileMapping(45) = nMapping
652
653Select Case nTile
654Case 0
655oCurrentLayer.Data.TileValue(nTileX, nTileY) = 29
656oSprite.UserData = nTileX + nTileY * 128
657Case 29
658oSprite.CurState = 6
659oSprite.DX = 0
660oSprite.DY = 0
661Exit Sub
662Case 45
663nTile = nMapping
664End Select
665
666If (oSprite.DX = 0 And oSprite.DY = 0) Or _
667((nX Mod TileSize) = 0 And (nY Mod TileSize) = 0) Then
668If nTileY < oCurrentLayer.Rows - 1 Then
669With oCurrentLayer.Data
670nTileBelowLeft = .TileValue(nX \ TileSize, nY \ TileSize + 1)
671nTileBelowRight = .TileValue((nX + TileSizeMinus1) \ TileSize, nY \ TileSize + 1)
672nTileLeftFoot = .TileValue(nX \ TileSize, (nY + TileSizeMinus1) \ TileSize)
673nTileRightFoot = .TileValue((nX + TileSizeMinus1) \ TileSize, (nY + TileSizeMinus1) \ TileSize)
674End With
675If Not (oStopFallGroup.IsMember(nTileBelowLeft) Or _
676oStopFallGroup.IsMember(nTileBelowRight) Or _
677oBarGroup.IsMember(nTileLeftFoot) Or _
678oBarGroup.IsMember(nTileRightFoot)) Then
679' Fall
680oSprite.CurState = 6
681oSprite.DX = 0
682oSprite.DY = 1
683Exit Sub
684End If
685End If
686Select Case oEnemyPathData.TileValue(nTileX, nTileY) And 3
687Case 1
688If oCurrentLayer.Data.TileValue(nTileX+1, nTileY) <> 29 Then
689If oBarGroup.IsMember(nTile) Then
690oSprite.CurState = 5
691Else
692oSprite.CurState = 1
693End If
694oSprite.DY = 0
695oSprite.DX = 1
696Else
697oSprite.CurState = 6
698oSprite.DX = 0
699oSprite.DY = 0
700End If
701Exit Sub
702Case 2
703If Not (nTileBelowLeft=29 Or nTileBelowRight=29) Then
704oSprite.CurState = 3
705oSprite.DX = 0
706oSprite.DY = 1
707Else
708oSprite.CurState = 6
709oSprite.DX = 0
710oSprite.DY = 0
711End If
712Exit Sub
713Case 3
714If oCurrentLayer.Data.TileValue(nTileX-1, nTileY) <> 29 Then
715If oBarGroup.IsMember(nTile) Then
716oSprite.CurState = 4
717Else
718oSprite.CurState = 0
719End If
720oSprite.DY = 0
721oSprite.DX = -1
722Else
723oSprite.CurState = 6
724oSprite.DX = 0
725oSprite.DY = 0
726End If
727Exit Sub
728Case Else
729If oLadderGroup.IsMember(nTile) Then
730oSprite.CurState = 2
731oSprite.DX = 0
732oSprite.DY = -1
733Exit Sub
734End If
735If nTileX > 0 Then
736If Not oWalkSolidGroup.IsMember(oCurrentLayer.Data.TileValue(nTileX-1, nTileY)) Then
737If oCurrentLayer.Data.TileValue(nTileX-1, nTileY) <> 29 Then
738If oBarGroup.IsMember(nTile) Then
739oSprite.CurState = 4
740Else
741oSprite.CurState = 0
742End If
743oSprite.DY = 0
744oSprite.DX = -1
745Else
746oSprite.CurState = 6
747oSprite.DX = 0
748oSprite.DY = 0
749End If
750Exit Sub
751End If
752End If
753If nTileX < oCurrentLayer.Data.TileValue(nTileX+1, nTileY) Then
754If Not oWalkSolidGroup.IsMember(oCurrentLayer.Data.TileValue(nTileX+1, nTileY)) Then
755If oCurrentLayer.Data.TileValue(nTileX-1, nTileY) <> 29 Then
756If oBarGroup.IsMember(nTile) Then
757oSprite.CurState = 5
758Else
759oSprite.CurState = 1
760End If
761oSprite.DY = 0
762oSprite.DX = 1
763Else
764oSprite.CurState = 6
765oSprite.DX = 0
766oSprite.DY = 0
767End If
768Exit Sub
769End If
770End If
771End Select
772End If
773End Sub
774
775Function SearchStep(ByVal nDepth, ByVal bImmediate)
776Dim nX, nY
777Dim nPTile, nPTileLeft, nPTileRight, nPTileAbove, nPTileBelow
778Dim nDTile, nDTileLeft, nDTileRight, nDTileAbove, nDTileBelow
779Dim bLadder, bMoveOK
780
781' Path byte values, low 2 bits:
782' 0 = Go up to reach player
783' 1 = Go right to reach player
784' 2 = Go down to reach player
785' 3 = Go left to reach player
786' next bit (4):
787' 0 = Iteration A path
788' 4 = Iteration B path
789' next bit (8):
790' 0 = Can't fall from above
791' 8 = Can fall from above
792
793If nQueueSize = 0 Then PlayerSeedSearch
794
795Do While nDepth > 0 And nQueueSize > 0
796If bImmediate Then
797nX = (nCurX + HalfTileSize) \ TileSize
798nY = (nCurY + HalfTileSize) \ TileSize
799Else
800' Dequeue a coordinate
801nX = arSearchQueue(nQueueStart) And 127
802nY = arSearchQueue(nQueueStart) \ 128
803nQueueStart = (nQueueStart + 1) Mod nQueueBufSize
804nQueueSize = nQueueSize - 1
805End If
806
807nPTile = oEnemyPathData.TileValue(nX, nY)
808nDTile = oCurrentLayer.Data.TileValue(nX, nY)
809bLadder = oLadderGroup.IsMember(nDTile)
810' Only process this coordinate if it's walkable
811If bLadder Or Not oWalkSolidGroup.IsMember(nDTile) Then
812If nY>0 Then
813nPTileAbove = oEnemyPathData.TileValue(nX, nY-1)
814If (bImmediate Or (nPTileAbove And 4) <> nIteration) Then
815' Path has not been calculated for this iteration
816If (nPTile And 8) Or bLadder Then ' Can come from above
817oEnemyPathData.TileValue(nX, nY-1) = (nPTileAbove And Not 7) Or 2 Or nIteration
818If Not bImmediate Then
819' Enqueue above tile for search
820arSearchQueue((nQueueStart + nQueueSize) Mod nQueueBufSize) = nX + (nY-1) * 128
821nQueueSize = nQueueSize + 1
822End If
823End If
824End If
825End If
826If nX > 0 Then
827nDTileLeft = oCurrentLayer.Data.TileValue(nX-1, nY)
828If nY < oCurrentLayer.Rows-1 Then
829bMoveOK = oStopFallGroup.IsMember(oCurrentLayer.Data.TileValue(nX-1, nY+1)) Or _
830oBarGroup.IsMember(nDTileLeft)
831Else
832bMoveOK = True
833End If
834If bMoveOK Then
835nPTileLeft = oEnemyPathData.TileValue(nX-1,nY)
836If (bImmediate Or ((nPTileLeft And 4) <> nIteration)) And _
837Not oClimbSolidGroup.IsMember(nDTileLeft) Then
838oEnemyPathData.TileValue(nX-1, nY) = (nPTileLeft And Not 7) Or 1 Or nIteration
839If Not bImmediate Then
840' Enqueue left tile for search
841arSearchQueue((nQueueStart + nQueueSize) Mod nQueueBufSize) = nX-1 + nY * 128
842nQueueSize = nQueueSize + 1
843End If
844End If
845End If
846End If
847If nX < oCurrentLayer.Columns-1 Then
848nDTileRight = oCurrentLayer.Data.TileValue(nX+1, nY)
849If nY < oCurrentLayer.Rows-1 Then
850bMoveOK = oStopFallGroup.IsMember(oCurrentLayer.Data.TileValue(nX+1, nY+1)) Or _
851oBarGroup.IsMember(nDTileRight)
852Else
853bMoveOK = True
854End If
855If bMoveOK Then
856nPTileRight = oEnemyPathData.TileValue(nX+1, nY)
857If (bImmediate Or ((nPTileRight And 4) <> nIteration)) And _
858Not oClimbSolidGroup.IsMember(nDTileRight) Then
859oEnemyPathData.TileValue(nX+1, nY) = (nPTileRight And Not 7) Or 3 Or nIteration
860If Not bImmediate Then
861' Enqueue right tile for search
862arSearchQueue((nQueueStart + nQueueSize) Mod nQueueBufSize) = nX+1 + nY * 128
863nQueueSize = nQueueSize + 1
864End If
865End If
866End If
867End If
868If nY < oCurrentLayer.Rows - 1 Then
869nDTileBelow = oCurrentLayer.Data.TileValue(nX, nY+1)
870nPTileBelow = oEnemyPathData.TileValue(nX, nY+1)
871If (bImmediate Or ((nPTileBelow And 4) <> nIteration)) And oLadderGroup.IsMember(nDTileBelow) Then
872oEnemyPathData.TileValue(nX, nY+1) = (nPTileBelow And Not 7) Or nIteration
873If Not bImmediate Then
874' Enqueue Below tile for search
875arSearchQueue((nQueueStart + nQueueSize) Mod nQueueBufSize) = nX + (nY+1) * 128
876nQueueSize = nQueueSize + 1
877End If
878End If
879End If
880End If
881nDepth = nDepth - 1
882Loop
883End Function
884
885Sub Player_OnPlayInit()
886ProjectObj.Maps("Intro").RemoveSpecial("ScriptGuard")
887End Sub
888
889HostObj.SinkObjectEvents ProjectObj.GamePlayer, "Player"
890HostObj.ConnectEventsNow()
891ProjectObj.GamePlayer.bIgnoreValidate = True
892ProjectObj.GamePlayer.Play 16