-
Notifications
You must be signed in to change notification settings - Fork 0
/
Nebunoid.bi
1560 lines (1406 loc) · 45.8 KB
/
Nebunoid.bi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include "ABCgfx.bi"
#include "fbgfx.bi"
using FB
#include "vbcompat.bi"
dim shared as string QuickPlayFile
declare sub local_gameplay
const PlaytestName = "Quick Playtest Level"
const EndlessFolder = "official/endless"
const AIName = "Nebunoid Intelligence"
const DummyName = "Pumpkin Eater"
'Speed range specs
const DefaultSpeed = 8
const MinSpeed = 6
randomize timer
dim shared as uinteger ReservedMB
dim shared as string NullString, Masterdir
dim as byte ScreenCreated = 0
dim shared as byte MusicPlrEnabled
dim shared as any ptr TitleBanner
Masterdir = curdir
#IFDEF __USE_SDL__
#include "NebSDL.bas"
#ELSEIF defined(__USE_FBSOUND__)
#DEFINE __DISABLE_PI__
#include "NebFBS.bas"
#ELSE
#include "NebNull.bas"
#ENDIF
#IFDEF __FB_WIN32__
#include "windows.bi"
#ENDIF
#include "WordWrap.bi"
declare sub shop
declare sub generate_capsule(InX as byte, InY as byte, Explode as ubyte = 0)
'Keyboard commands
const EscapeKey = chr(27)
const UpArrow = chr(255,72)
const DownArrow = chr(255,80)
const LeftArrow = chr(255,75)
const RightArrow = chr(255,77)
const PageUp = chr(255,73)
const PageDn = chr(255,81)
const EnterKey = chr(13)
const Backspace = chr(8)
const XBox = chr(255,107)
const FunctionOne = chr(255,59)
const FunctionFour = chr(255,62)
const FunctionFive = chr(255,63)
const FunctionSeven = chr(255,65)
const FunctionEleven = chr(255,133)
const FunctionTwelve = chr(255,134)
const FPS = 60
const SavedHighSlots = 10
const TotalHighSlots = SavedHighSlots + 4
const TotalOfficialLevels = 323
const MaxBullets = 60
const BaseFlash = 128
const LevelClearDelay = 720
const ExplodeDelay = -6
enum Difficulties
DIFF_KIDS = 1
DIFF_VEASY
DIFF_EASY
DIFF_MEASY
DIFF_MEDIUM
DIFF_MHARD
DIFF_HARD
DIFF_VHARD
DIFF_EXTREME
DIFF_INSANE
end enum
enum DifferentGames
STYLE_POWERUPS
STYLE_EXTRA_HEIGHT
STYLE_DUAL_PADDLES
STYLE_DOUBLE_BALLS
STYLE_CAVITY
STYLE_PROGRESSIVE
STYLE_STEER
STYLE_INVIS
STYLE_HYPER
STYLE_BOSS
STYLE_ROTATION
STYLE_FUSION
STYLE_SHRINK_CEILING
STYLE_BREAKABLE_CEILING
STYLE_FATAL_TIMER
STYLE_BONUS
end enum
enum CapsuleDesigns
CAP_SLOW = 1
CAP_FAST
CAP_EXPAND
CAP_REDUCE
CAP_LIFE
CAP_BLIZZARD
CAP_ZAP
CAP_SPLIT_BALL
CAP_DISRUPT
CAP_MYSTERY
CAP_MAXIMIZE
CAP_GRAB
CAP_SLOW_PAD
CAP_WEP_BULLET
CAP_WEP_MISSILE
CAP_REVERSE
CAP_SPREAD
CAP_DETONATE
CAP_EXTENDER
CAP_NEGATER
CAP_WEAK
CAP_FIRE
CAP_THRU
CAP_GRAVITY
CAP_WARP
CAP_REPAIR
CAP_GEM_R
CAP_GEM_G
CAP_GEM_B
CAP_GEM_Y
CAP_GEM_P
CAP_GEM_C
CAP_GEM_W
CAP_MAX
end enum
enum ControlTypes
CTRL_AI = -1
CTRL_DESKTOP
CTRL_LAPTOP
CTRL_TABLET
CTRL_KEYBOARD
CTRL_JOYSTICK1
CTRL_JOYSTICK2
CTRL_JOYSTICK3
CTRL_JOYSTICK4
end enum
const PAD_XS = 40
const PAD_SM = 80
const PAD_MED = 120
const PAD_LG = 160
const PAD_XL = 240
const PAD_2XL = 360
const PAD_3XL = 480
enum BallDesigns
BALL_SM = 3
BALL_MED
BALL_LG
end enum
type Basics
'Common Stuff
X as single
Y as single
Spawned as ubyte
Grabbed as double
'Ball Stuff
LHX as ubyte
LHY as ubyte
Angle as single
Speed as single
Invul as ushort
Trapped as short
Power as integer
Duration as short
Gravity as ushort
ForceUngrab as ushort
'Paddle Stuff
Repairs as short
Grabbing as short
Sluggish as short
Reverse as short
Blizzard as short
Fireball as short
Breakthru as short
WeakDmg as short
GravBall as short
end type
type ParticleSpecs
X as Single
Y as single
XSpd as single
YSpd as single
Blending as short
Coloring as uinteger
end type
type PalleteSpecs
PColoring as uinteger
ScoreValue as ushort
DynamicValue as ubyte
CanRegen as ubyte
HitDegrade as byte
ZapDegrade as short
IncreaseSpeed as ubyte
CalcedInvulnerable as byte
UsedInlevel as ubyte
TimesRespawned as ushort
end type
type TileSpecs
BrickID as short
BaseBricKID as short
Flash as short
HitTime as short
LastBall as short
end type
type BackSpecs
Filename as string
end type
type PlayerSpecs
DispScore as uinteger
Score as uinteger
Lives as short
Threshold as uinteger
PerfectClear as byte
GameOverCombo as byte
Difficulty as double
BulletAmmo as short
MissileAmmo as short
PlayTime as integer
WarpTimer as short
BossHealth as integer
BossMaxHealth as integer
BossLastHealth as integer
BossLastHit as short
LevelTimer as integer
InitialLevel as short
LevelNum as short
PokerHand(5) as byte
SetCleared as byte
Tileset(41,24) as TileSpecs
SavedGameStyle as uinteger
end type
type LevelsetSpecs
Namee as string
Folder as string
Difficulty as string
SetSize as integer
TrueSize as integer
StarsToUnlock as integer
SetLocked as byte
SetMastered as byte
end type
type HighSlot
Namee as string
RawScore as uinteger
GameTime as integer
LevelStart as integer
LevelFinal as integer
Difficulty as double
NewEntry as byte
end type
const ZapBrush = 36
const BloomBrush = ZapBrush + 1
const SwapBrush = ZapBrush + 2
const MaxPlayers = 6
dim shared as PlayerSpecs PlayerSlot(MaxPlayers), NewPlrSlot
dim shared as PalleteSpecs Pallete(SwapBrush)
dim shared as FB.event e
const MISC = 3
const ExplodeAniRate = 1
const NumBalls = 128
const MaxFallCaps = 12
const Particount = 2500
const BackCount = 99
dim shared as ushort MinSize, StandardSize, MaxSize, CapsFalling, BulletsInPlay, _
Credits, CoinsPerCredit, CeleYear, BrickCount, XplodeCount, ZappableCount, Combo
dim shared as short PaddleSize, HintLevel, CampaignBarrier, BulletStart, BacksLoaded, BoxGlow
dim shared as HighSlot HighScore(TotalHighSlots)
dim shared as uinteger MouseX, MouseY, MouseColor, ButtonCombo, TotalXP, TotalStars
dim shared as uinteger GameStyle, TourneyStyle, TourneyScore, ShotIndex
dim shared as ubyte Fullscreen, ConfigLoaded = 0, JoyAnalog, JoyInvertAxes, TapWindow, CondensedLevel, AllowHandicap, ShuffleLevels
dim shared as integer LastActive, Result, OrigX(1), DesireX, JoyButtonCombo, ExplodingValue, BGBrightness
dim shared as single JoyAxis(7)
dim shared as short TotalBC, FrameSkip, PaddleCycle, ExplodeCycle, KeyboardSpeed, JoyKeySetting, ProgressiveBounces, ProgressiveDelay, BlockBrushes
dim shared as double ProgressiveQuota, InstructExpire, MisnExpire, TimeRem, Reminder = -1, _
FrameTime, PaddlePercent, DifficultyRAM(MaxPlayers)
dim shared as string InType, ScoreFile, Instructions, CampaignFolder, BackList(BackCount), DiffTxt
dim shared as BackSpecs BackSlot(BackCount)
dim shared as Basics Paddle(2), Capsule(MaxFallCaps), Ball(NumBalls), Bullet(MaxBullets), LaserBeams(20,15)
dim shared as ParticleSpecs Particles(Particount)
dim shared as ubyte DQ, Player, NumPlayers, DispLives, Invis, GfxStyle, ExploTick, _
BallSize, MenuMode, HoldClick, HoldAction
dim shared as byte EnhancedGFX, GamePaused, TourneyValid, TotalMessages, TotalUnread, ControlStyle, SavedControls
dim shared as any ptr BulletPic, MissilePic, CapsulePic(26), CapsuleBar(9), CapsuleBarFrame, PokerBar(5), Background, PaddlePic, _
SoftBrickPic, MultihitPic, InvinciblePic, ExplodePic, BaseExplode, SoftBrickConnL, SoftBrickConnR, SoftBrickConnT, SoftBrickConnB, _
MultihitConnL, MultihitConnR, MultihitConnT, MultihitConnB, InvincibleConnL, InvincibleConnR, InvincibleConnT, InvincibleConnB, _
SoftBrickPicMini, MultihitMini, InvincibleMini, SoftBrickConnMiniL, SoftBrickConnMiniR, SoftBrickConnMiniT, SoftBrickConnMiniB, _
MultihitConnMiniL, MultihitConnMiniR, MultihitConnMiniT, MultihitConnMiniB, _
InvincibleConnMiniL, InvincibleConnMiniR, InvincibleConnMiniT, InvincibleConnMiniB, _
FramesetMerged, Sideframes, Topframe, DiffStick, DiffSelector, BasePaddle, PaddleBar
const Interpolation = 120 'Ball updates per frame
const CampaignsPerPage = 13
const CustomizePerPage = 20
const PaddleHeight = 18
const CustomizePadding = 60
const CustomizeSelect = CustomizePadding - 5
dim shared as LevelsetSpecs OfficialCampaigns(CampaignsPerPage+1), CommunityCampaigns()
enum BounceDirections
BOUNCE_E = 1
BOUNCE_NE
BOUNCE_N
BOUNCE_NW
BOUNCE_W
BOUNCE_SW
BOUNCE_S
BOUNCE_SE
end enum
function total_lives as integer
dim as integer LivesFound
for PID as ubyte = 1 to MaxPlayers
with PlayerSlot(PID)
LivesFound += .Lives
end with
next PID
return LivesFound
end function
sub read_campaigns(StarsOnly as ubyte = 0)
dim as integer CommunityFoldersFound = 0, LevelsCleared
dim as string CommunityFolder
TotalStars = 0
for OCID as ubyte = 1 to CampaignsPerPage+1 'Official campaigns first
with OfficialCampaigns(OCID)
.TrueSize = 0
select case OCID
case 1
.Namee = "Introductory Training"
.Folder = "official/intro"
.Difficulty = "Easy"
.SetSize = 10
case 2
.Namee = "Geometric Designs"
.Folder = "official/geometry"
.Difficulty = "Easy to Medium"
.SetSize = 10
.TrueSize = 15
case 3
.Namee = "Times of the Year"
.Folder = "official/annual"
.Difficulty = "Easy to Medium"
.SetSize = 12
case 4
.Namee = "Regular Season"
.Folder = "official/regular"
.Difficulty = "Easy to Hard"
.SetSize = 30
.TrueSize = 35
case 5
.Namee = "Fortified Letters"
.Folder = "official/alphabet"
.Difficulty = "Easy to Hard"
.SetSize = 26
case 6
.Namee = "Electric Recharge"
.Folder = "official/electric"
.Difficulty = "Easy to Hard"
.SetSize = 20
.TrueSize = 25
case 7
.Namee = "Patriarch Memorial"
.Folder = "official/memorial"
.Difficulty = "Medium to Hard"
.SetSize = 25
case 8
.Namee = "Fusion Designs"
.Folder = "official/fusion"
.Difficulty = "Medium to Hard"
.SetSize = 20
.StarsToUnlock = 15
case 9
.Namee = "Challenge Campaign"
.Folder = "official/challenge"
.Difficulty = "Hard to Extreme"
.SetSize = 30
.TrueSize = 35
.StarsToUnlock = 25
case 10
.Namee = "Ungated Adaptations"
.Folder = "official/ungated"
.Difficulty = "Hard to Extreme"
.SetSize = 40
.StarsToUnlock = 50
case 11
.Namee = "Maximum Insanity"
.Folder = "official/extreme"
.Difficulty = "Very Hard to Extreme"
.SetSize = 30
.StarsToUnlock = 100
case 12
.Namee = "Celestial Journey"
.Folder = "official/universe"
.Difficulty = "Hard to Extreme"
.SetSize = 40
.TrueSize = 50
.StarsToUnlock = 150
case 13
.Namee = "Endless Shuffle"
.Folder = "official/endless"
.Difficulty = "Unpredictable"
.SetSize = 1000
if TotalStars >= 288 then
.StarsToUnlock = TotalOfficialLevels 'ALL of the previous levels
else
.StarsToUnlock = 1000 'Keep the player from knowing the exact requirement at first
end if
case CampaignsPerPage+1
.Namee = "(Community campaigns)"
.SetSize = 0
case else
.Namee = ""
.SetSize = 0
.SetLocked = -1
end select
if .Namee <> "" AND .Folder <> EndlessFolder then
if .TrueSize = 0 then
.TrueSize = .SetSize
end if
if FileExists(.Namee+".dat") then
open .Namee+".dat" for input as #19
input #19, LevelsCleared
close #19
.SetMastered = -abs(sgn(FileExists(.Namee+".flag")))
if .SetMastered AND LevelsCleared < .TrueSize then
/'
' Invalidate mastery if this was a false final level clear
' (Keep the star credit, though)
'/
.SetMastered = 0
elseif .SetMastered = 0 then
'Campaign has not been cleared; exclude a star from this calculation
LevelsCleared -= 1
end if
else
LevelsCleared = 0
end if
if OCID <= CampaignsPerPage then
'In case a player died on a secret level, register it as having been seen
.SetSize = max(.SetSize,LevelsCleared + 1 + .SetMastered)
TotalStars += LevelsCleared
end if
end if
end with
next OCID
if StarsOnly = 0 then
'Scan community campaigns afterwards
CommunityFolder = Dir(MasterDir+"/campaigns/community/*",fbDirectory)
while len( CommunityFolder ) > 0
if CommunityFolder <> "." AND CommunityFolder <> ".." then
CommunityFoldersFound += 1
redim preserve CommunityCampaigns(CommunityFoldersFound)
with CommunityCampaigns(CommunityFoldersFound)
.Namee = CommunityFolder
.Folder = "community/"+CommunityFolder
for LID as short = 1 to 999
if FileExists(MasterDir+"/campaigns/"+.Folder+"/L"+str(LID)+".txt") = 0 then
.SetSize = LID - 1
exit for
end if
next LID
end with
end if
CommunityFolder = Dir()
wend
OfficialCampaigns(CampaignsPerPage+1).SetSize = CommunityFoldersFound
end if
end sub
sub load_title_capsules
dim as string TitleCaps(1 to 26) => {"slow", "split", "grab", "spread", "detonate", "zap", "bullet", "blizzard", "fire", "thru", "missile", "warp", "life", _
"fast", "weak", "max", "gravity", "reverse", "slowpad", "", "expand", "reduce", "mystery", "disruption", "extender", "negater"}
for PID as byte = 1 to 26
if TitleCaps(PID) <> "" then
bload(Masterdir+"/gfx/caps/"+TitleCaps(PID)+".bmp",CapsulePic(PID))
end if
next PID
end sub
sub toggle_fullscreen(ForceSetting as byte = 0)
if (FullScreen = 0 OR ForceSetting = 1) AND ForceSetting <> -1 then
FullScreen = 1
screen 20,24,2,GFX_FULLSCREEN OR GFX_ALPHA_PRIMITIVES OR GFX_NO_SWITCH
screenset 1,0
setmouse(,,0,0)
open "FS.ini" for output as #9
close #9
else
FullScreen = 0
screen 20,24,2,GFX_ALPHA_PRIMITIVES OR GFX_NO_SWITCH
screenset 1,0
setmouse(,,0,0)
kill("FS.ini")
end if
end sub
sub draw_border(Model as any ptr, StartX as short, StartY as short, EndX as short, EndY as short, Opacity as short)
line Model,(StartX,StartY)-(EndX,StartY),rgba(255,255,255,Opacity)
line Model,(StartX,StartY)-(StartX,EndY),rgba(255,255,255,Opacity)
line Model,(EndX,StartY+1)-(EndX,EndY-1),rgba(0,0,0,Opacity)
line Model,(StartX+1,EndY)-(EndX,EndY),rgba(0,0,0,Opacity)
end sub
sub draw_box(StartX as short,StartY as short,EndX as short,EndY as short)
BoxGlow -= 3
if BoxGlow <= -128 then
BoxGlow += 255
end if
dim as uinteger DrawColor
dim as short PaintStr
for BID as short = 0 to 4
PaintStr = BoxGlow - (BID*24)
while PaintStr <= -128
PaintStr += 255
wend
DrawColor = rgba(255,128,128,128+abs(PaintStr))
line(StartX+BID,StartY+BID)-(EndX-BID,StartY+BID),DrawColor
line(StartX+BID,StartY+BID+1)-(StartX+BID,EndY-BID),DrawColor
line(EndX-BID,StartY+BID+1)-(EndX-BID,EndY-BID),DrawColor
line(StartX+BID+1,EndY-BID)-(EndX-BID-1,EndY-BID),DrawColor
next BID
end sub
sub get_difficulty_names(DifficultyAmt as double)
select case int(DifficultyAmt+0.5)
case DIFF_KIDS
DiffTxt = "Effortless"
case DIFF_VEASY
DiffTxt = "Very Easy"
case DIFF_EASY
DiffTxt = "Easy"
case DIFF_MEASY
DiffTxt = "Medium Easy"
case DIFF_MEDIUM
DiffTxt = "Medium"
case DIFF_MHARD
DiffTxt = "Medium Hard"
case DIFF_HARD
DiffTxt = "Hard"
case DIFF_VHARD
DiffTxt = "Very Hard"
case DIFF_EXTREME
DiffTxt = "Extreme"
case else
if DifficultyAmt < 11 then
DiffTxt = "Insane"
else
DiffTxt = "Nightmare"
end if
end select
end sub
sub render_paddle(NewSize as short)
if NewSize > 960 then
NewSize = 960
end if
PaddleSize = NewSize
PaddleCycle += 1
if PaddleCycle >= 120*10 then
PaddleCycle = 0
end if
put PaddlePic,(-int(PaddleCycle/10),0),BasePaddle,pset
line PaddlePic,(PaddleSize,0)-(1079,PaddleHeight-1),rgb(255,0,255),bf
for BID as ubyte = 0 to int(sqr(PaddleSize/20))
draw_border(PaddlePic,BID,BID,PaddleSize-1-BID,PaddleHeight-1-BID,255-BID*32)
next BID
end sub
sub particle_system
if EnhancedGFX > 0 then
for PID as ushort = 0 to Particount
with Particles(PID)
if .Y < 768 AND .Blending > 0 then
.Coloring = rgba(retrivePrimary(.Coloring,RGBA_RED),_
retrivePrimary(.Coloring,RGBA_GREEN),_
retrivePrimary(.Coloring,RGBA_BLUE),.Blending)
pset(.X,.Y),.Coloring
if .Blending > 0 then
.Blending -= 1
end if
.X += .XSpd
.Y += .YSpd
.YSpd += 1.6/60
end if
end with
next
else
for PID as ushort = 0 to Particount
with Particles(PID)
.Y = 800
.Blending = 0
end with
next
end if
end sub
sub generate_particles(NewCount as integer, XL as byte, YL as byte, _
ApplyColor as uinteger)
dim as integer NewParticle, FreeParticles, TrueCount
for PID as integer = 1 to Particount
with Particles(PID)
if .Y >= 768 OR .Blending <= 0 then
FreeParticles += 1
end if
end with
next PID
if NewCount <= 100 then
TrueCount = NewCount
else
TrueCount = 100 + int(sqr(NewCount - 100))
end if
for PID as integer = 1 to TrueCount
if FreeParticles = 0 then
exit for
end if
do
NewParticle = irandom(1,Particount)
loop until Particles(NewParticle).Y >= 768 OR _
Particles(NewParticle).Blending <= 0
with Particles(NewParticle)
.X = 32 + ((XL - 1) * 48 + irandom(12,36))/(CondensedLevel+1)
.Y = (YL - 1) * 24 + irandom(102,114)
.YSpd = rnd * -2.5
.XSpd = (rnd - 0.5) * 2
.Blending = 255
.Coloring = ApplyColor
end with
FreeParticles -= 1
next PID
end sub
sub force_release_balls
for BID as short = 1 to NumBalls
with Ball(BID)
if .Grabbed > 0 then
.Grabbed = int(.Grabbed/1000)*1000 + 1
end if
.ForceUngrab = 6
end with
next
end sub
sub optimal_direction(InBall as short, BrickX as byte, BrickY as byte)
dim as short StartX, BWidth, StartY, BHeight
dim as double CenterX, CenterY, PreviousX, PreviousY, DeltaX, DeltaY, NewDX, NewDY, NewDZ, InternalMultiplier
dim as ubyte BounceAngle, SwapSpecs
'Determine the coordinates and specs of the brick in question
BWidth = 48/(CondensedLevel + 1)
BHeight = 24
StartX = 32+(BrickX-1)*BWidth
StartY = 96+(BrickY-1)*BHeight
'Consolidate adjacent bricks to form a larger mass
if BrickX = 1 OR PlayerSlot(Player).TileSet(int(BrickX-1),BrickY).BrickID > 0 then
StartX -= 48/(CondensedLevel + 1)
BWidth += 48/(CondensedLevel + 1)
end if
if BrickX >= 20 * (CondensedLevel + 1) OR PlayerSlot(Player).TileSet(int(BrickX+1),BrickY).BrickID > 0 then
BWidth += 48/(CondensedLevel + 1)
end if
if BrickY > 1 AND PlayerSlot(Player).TileSet(BrickX,int(BrickY-1)).BrickID > 0 then
StartY -= 24
BHeight += 24
end if
if BrickY < 20 AND PlayerSlot(Player).TileSet(BrickX,int(BrickY+1)).BrickID > 0 then
BHeight += 24
end if
CenterX = StartX + BWidth/2
CenterY = StartY + BHeight/2
'Use the current vector and previous position
with Ball(InBall)
InternalMultiplier = int(.Speed) / 1.3 / Interpolation
if (GameStyle AND (1 SHL STYLE_HYPER)) then
InternalMultiplier *= 1.5
end if
DeltaX = cos(degtorad(.Angle))
DeltaY = -sin(degtorad(.Angle))
PreviousX = .X - DeltaX * InternalMultiplier
PreviousY = .Y - DeltaY * InternalMultiplier
NewDX = DeltaX
NewDY = -DeltaY
if (PreviousY >= StartY + BHeight) then
BounceAngle = BOUNCE_S
elseif (PreviousY <= StartY) then
BounceAngle = BOUNCE_N
end if
if (PreviousX < StartX) then
if BounceAngle = BOUNCE_S then
BounceAngle = BOUNCE_SW
elseif BounceAngle = BOUNCE_N then
BounceAngle = BOUNCE_NW
else
BounceAngle = BOUNCE_W
end if
elseif (PreviousX > StartX + BWidth) then
if BounceAngle = BOUNCE_S then
BounceAngle = BOUNCE_SE
elseif BounceAngle = BOUNCE_N then
BounceAngle = BOUNCE_NE
else
BounceAngle = BOUNCE_E
end if
end if
end with
if BounceAngle = BOUNCE_NE OR BounceAngle = BOUNCE_NW then
BounceAngle = BOUNCE_N
elseif BounceAngle = BOUNCE_SE OR BounceAngle = BOUNCE_SW then
BounceAngle = BOUNCE_S
end if
select case BounceAngle
case BOUNCE_E
NewDX = abs(DeltaX)
case BOUNCE_NE
NewDX = abs(DeltaX)
NewDY = abs(DeltaY)
case BOUNCE_N
NewDY = abs(DeltaY)
if NewDY = 0 then
NewDY = -1
end if
case BOUNCE_NW
NewDX = -abs(DeltaX)
NewDY = abs(DeltaY)
case BOUNCE_W
NewDX = -abs(DeltaX)
case BOUNCE_SW
NewDX = -abs(DeltaX)
NewDY = -abs(DeltaY)
case BOUNCE_S
NewDY = -abs(DeltaY)
if NewDY = 0 then
NewDY = -1
end if
case BOUNCE_SE
NewDX = abs(DeltaX)
NewDY = -abs(DeltaY)
end select
if SwapSpecs then
NewDZ = NewDX
NewDX = NewDY
NewDY = NewDZ
end if
with Ball(InBall)
.Angle = 3600 + radtodeg(atn(NewDY/NewDX))
if NewDX < 0 then
.Angle += 180
end if
end with
end sub
sub save_config
open "conf.ini" for output as #10
for Plr as byte = 1 to MaxPlayers
print #10, "difficulty,"& PlayerSlot(Plr).Difficulty
next Plr
print #10, "handicap,";AllowHandicap
print #10, "hintlv,"& HintLevel
print #10, "enhanced,"& EnhancedGFX
print #10, "controls,"& ControlStyle
print #10, "campbarr,"& CampaignBarrier
print #10, "shuffle,";ShuffleLevels
print #10, "bgbright,"& BGBrightness
print #10, "musplayer,"& MusicPlrEnabled
print #10, "xp,"& TotalXP
close #10
kill("xp.dat")
end sub
sub load_config
if ConfigLoaded = 0 AND FileExists("conf.ini") then
dim as byte PlayersFound = 0
open "conf.ini" for input as #10
do
input #10, NullString
select case NullString
case "difficulty"
PlayersFound += 1
if PlayersFound <= MaxPlayers then
with PlayerSlot(PlayersFound)
input #10, .Difficulty
.Difficulty = max(.Difficulty,1.0)
end with
else
input #10, NullString
end if
case "handicap"
input #10, AllowHandicap
case "hintlv"
input #10, HintLevel
case "enhanced"
input #10, EnhancedGFX
case "controls"
input #10, ControlStyle
ControlStyle = max(ControlStyle,CTRL_DESKTOP)
case "campbarr"
input #10, CampaignBarrier
case "shuffle"
input #10, ShuffleLevels
case "musplayer"
input #10, MusicPlrEnabled
case "bgbright"
input #10, BGBrightness
BGBrightness = max(min(BGBrightness,100),0)
case "xp"
input #10, TotalXP
end select
loop until eof(10)
close #10
ConfigLoaded = 1
end if
end sub
function ball_ct_bonus as byte
'The Computer Player does not benefit from Multiball bonus
if ControlStyle = CTRL_AI then
return 1
end if
'Otherwise, more balls = more points per block; subject to Diminishing Returns
return int(sqr(TotalBC) + 0.5)
end function
sub respawn_blocks(BrushID as short)
dim as ushort BlocksRespawned = 0
'Respawns all blocks that were origianlly bound to the selected brush
for YID as ubyte = 1 to 24
for XID as ubyte = 1 to 20*(CondensedLevel+1)
with PlayerSlot(Player).TileSet(XID,YID)
if .BrickID = 0 AND .BaseBrickID = BrushID then
BlocksRespawned += 1
.BrickID = .BaseBrickID
.Flash = BaseFlash - 1
end if
end with
next XID
next YID
if BlocksRespawned > 0 then
'Damages the ceiling slightly
with PlayerSlot(Player)
.BossLastHealth = .BossHealth
.BossLastHit = 0
.BossHealth -= max(int(.BossMaxHealth/100),1)
if .BossHealth <= 0 then
play_clip(SFX_WALL_BROKEN)
end if
end with
play_clip(SFX_BRICKS_RESPAWN)
end if
end sub
declare sub damage_brick(BaseX as short, BaseY as short, NewPalette as short, NewID as short = 0, OnlySelf as byte = 0)
function disp_wall(FrameTick as short, DispSetting as byte = 0) as integer
dim as ubyte AlphaV
dim as uinteger XColoring, ScoreBonus, Count, XPanning
dim as byte RefPallete, MaxY
dim as ubyte BlocksInPallete(35)
dim as string PrintChar
XplodeCount = 0
ZappableCount = 0
if ExploTick >= 6*(CondensedLevel+1) then
ExplodeCycle += 32
ExploTick = 0
end if
if ExplodeCycle >= 128*ExplodeAniRate then
ExplodeCycle = 0
end if
put ExplodePic,(-int(ExplodeCycle/ExplodeAniRate),0),BaseExplode,pset
if CondensedLevel then
line ExplodePic,(24,0)-(47,23),rgb(255,0,255),bf
if (Gamestyle AND (1 SHL STYLE_FUSION)) = 0 then
for BID as ubyte = 0 to 1
draw_border(ExplodePic,BID,BID,23-BID,23-BID,255-BID*127)
next BID
end if
elseif (Gamestyle AND (1 SHL STYLE_FUSION)) = 0 then
for BID as ubyte = 0 to 1
draw_border(ExplodePic,BID,BID,47-BID,23-BID,255-BID*127)
next BID
end if
if DispSetting = 2 then
MaxY = 24
else
MaxY = 20
end if
for YID as ubyte = 1 to 24
for XID as ubyte = 1 to 20*(CondensedLevel+1)
with PlayerSlot(Player).Tileset(XID,YID)
if YID <= MaxY then
if .BrickID <= -1 then
XColoring = rgba(255,128,0,128)
if .BrickID < -100 then
XColoring = rgba(0,128,255,128)
end if
if CondensedLevel then
XPanning = 48+(XID-1)*24
put(32+(XID-1)*24,96+(YID-1)*24),ExplodePic,trans
line(32+(XID-1)*24,96+(YID-1)*24)-_
(31+(XID)*24,95+(YID)*24),XColoring,bf
else
XPanning = 56+(XID-1)*48
put(32+(XID-1)*48,96+(YID-1)*24),ExplodePic,trans
line(32+(XID-1)*48,96+(YID-1)*24)-_
(31+(XID)*48,95+(YID)*24),XColoring,bf
end if
if GamePaused = 0 then
if .BrickID < -1 AND .BrickID <> -101 then
'Exploding in progress
.BrickID += 1
Invis = 12
else
dim as short FinalBrush = 0
if .BrickID = -101 then
'Make extra "Bloom" blocks
FinalBrush = BloomBrush
end if
'Finish exploding
for YDID as byte = YID - 1 to YID + 1
for XDID as byte = XID - 1 to XID + 1
if XDID > 0 AND XDID <= 20*(CondensedLevel+1) AND YDID > 0 AND YDID <= 20 then
RefPallete = PlayerSlot(Player).TileSet(XDID,YDID).BrickID
if (RefPallete >= 0 AND RefPallete <> FinalBrush) OR (XDID = XID AND YDID = YID) then
if (RefPallete >= 0 AND Pallete(RefPallete).CalcedInvulnerable >= 0) OR _
(XDID = XID AND YDID = YID) then
if RefPallete = 0 then
ScoreBonus = 0
elseif TotalBC > 0 then
ScoreBonus = ball_ct_bonus * ExplodingValue
elseif total_lives > 0 then
ScoreBonus = ExplodingValue
end if
PlayerSlot(Player).Score += ScoreBonus
damage_brick(XDID,YDID,FinalBrush,0,(XDID = XID AND YDID = YID))
Invis = 12
generate_capsule(XDID,YDID,1)
generate_particles(ScoreBonus,XDID,YDID,rgb(255,192,160))